Avatar billede jsc Nybegynder
06. november 2003 - 16:05 Der er 12 kommentarer og
1 løsning

Automatisk sluk ved brug af "shutdown -s"

Hej Eksperter...

Jeg lukker ved at køre "shutdown -s" i start->kør, men når man gør det, så slukker den ikke selv, den kommer bare til skærm med at nu kan man slukke.

Jeg har set på forskellige spørgsmål og der er mange der nævner APM, men jeg har ACPI understøttet og kan iøvrigt ikke se den hak-boks i strømstyring - desuden slukker den jo fint nok når det gøres almindeligt, men hvordan/hvad gør man ved mit problem?

/jsc
Avatar billede driis Nybegynder
06. november 2003 - 16:20 #1
Prøv at hente denne:
http://www.driis.mobilixnet.dk/shutdwn.exe

Hvis ikke den kan lukke og slukke for strømmen, er der noget galt med dine indstillinger.
Avatar billede jsc Nybegynder
06. november 2003 - 16:25 #2
dit program virker fint.. men det er jo ikke det jeg vil.. jeg er igang med et vb-program hvor jeg vil bruge "shutdown -s" kommandoen - hvad gør du i programmet?
Avatar billede driis Nybegynder
06. november 2003 - 17:34 #3
Jeg vidste ikke det skulle bruges til dit eget program ;-)
shutdwn.exe er et program jeg selv har lavet til formålet, da jeg havde samme problem. Jeg har kildekoden i C, hvis du vil se den ?
Avatar billede driis Nybegynder
06. november 2003 - 17:48 #4
Hvis du tilføjer flg. til et VB modul, kan du lukke maskinen ved at kalde ShutDownSystem:

Option Explicit
Private Declare Function ExitWindowsEx Lib "user32" (ByVal uFlags As Long, ByVal dwReserved As Long) As Long
Declare Function LockWorkStation Lib "user32.dll" () As Long
Private Const ENDSESSION_LOGOFF = &H80000000
Dim Pos As Long
Dim GoShut As Boolean
Dim ret As Long
Dim uFlag As Long

Public Enum EShutDownTypes
    [_First] = 0
    EWX_LOGOFF = 0
    EWX_SHUTDOWN = 1&
    EWX_REBOOT = 2&
    EWX_FORCE = 4&
    EWX_POWEROFF = 8&
    EWX_FORCEIFHUNG = 10& ' kun NT5
   
    EWX_RESET = EWX_LOGOFF Or EWX_FORCE Or EWX_REBOOT
    [_Last] = &H20& - 1
End Enum
Public Enum EShutDownErrorBaseConstant
    eeSSDErrorBase = vbObjectError Or (1048 + &H210)
End Enum

Private Type OSVERSIONINFO
    dwOSVersionInfoSize As Long
    dwMajorVersion As Long
    dwMinorVersion As Long
    dwBuildNumber As Long
    dwPlatformId As Long
        szCSDVersion As String * 128
End Type
Private Declare Function GetVersionEx Lib "kernel32" Alias "GetVersionExA" (lpVersionInformation As OSVERSIONINFO) As Long
Private Const VER_PLATFORM_WIN32_NT = 2
Private Const VER_PLATFORM_WIN32_WINDOWS = 1
Private Const VER_PLATFORM_WIN32s = 0

' To Report API errors:
Private Const FORMAT_MESSAGE_ALLOCATE_BUFFER = &H100
Private Const FORMAT_MESSAGE_ARGUMENT_ARRAY = &H2000
Private Const FORMAT_MESSAGE_FROM_HMODULE = &H800
Private Const FORMAT_MESSAGE_FROM_STRING = &H400
Private Const FORMAT_MESSAGE_FROM_SYSTEM = &H1000
Private Const FORMAT_MESSAGE_IGNORE_INSERTS = &H200
Private Const FORMAT_MESSAGE_MAX_WIDTH_MASK = &HFF
Private Declare Function FormatMessage Lib "kernel32" Alias "FormatMessageA" (ByVal dwFlags As Long, lpSource As Any, ByVal dwMessageId As Long, ByVal dwLanguageId As Long, ByVal lpBuffer As String, ByVal nSize As Long, Arguments As Long) As Long


' ============================================================================================
' NT Only
Private Type LARGE_INTEGER
    LowPart As Long
    HighPart As Long
End Type
Private Type LUID
    LowPart As Long
    HighPart As Long
End Type
Private Type LUID_AND_ATTRIBUTES
    pLuid As LUID
    Attributes As Long
End Type
Private Type TOKEN_PRIVILEGES
    PrivilegeCount As Long
    Privileges(0 To 0) As LUID_AND_ATTRIBUTES
End Type
Private Declare Function GetCurrentProcess Lib "kernel32" () As Long
Private Declare Function OpenProcessToken Lib "advapi32.dll" (ByVal ProcessHandle As Long, ByVal DesiredAccess As Long, TokenHandle As Long) As Long
Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long
Private Declare Function GetTokenInformation Lib "advapi32.dll" (ByVal TokenHandle As Long, TokenInformationClass As Integer, TokenInformation As Any, ByVal TokenInformationLength As Long, ReturnLength As Long) As Long
Private Declare Function AdjustTokenPrivileges Lib "advapi32.dll" (ByVal TokenHandle As Long, ByVal DisableAllPrivileges As Long, NewState As TOKEN_PRIVILEGES, ByVal BufferLength As Long, PreviousState As TOKEN_PRIVILEGES, ReturnLength As Long) As Long
Private Declare Function LookupPrivilegeValue Lib "advapi32.dll" Alias "LookupPrivilegeValueA" (ByVal lpSystemName As String, ByVal lpName As String, lpLuid As LUID) As Long
Private Const SE_SHUTDOWN_NAME = "SeShutdownPrivilege"
Private Const SE_PRIVILEGE_ENABLED = &H2

Private Const READ_CONTROL = &H20000
Private Const STANDARD_RIGHTS_ALL = &H1F0000
Private Const STANDARD_RIGHTS_EXECUTE = (READ_CONTROL)
Private Const STANDARD_RIGHTS_READ = (READ_CONTROL)
Private Const STANDARD_RIGHTS_REQUIRED = &HF0000
Private Const STANDARD_RIGHTS_WRITE = (READ_CONTROL)

Private Const TOKEN_ASSIGN_PRIMARY = &H1
Private Const TOKEN_DUPLICATE = (&H2)
Private Const TOKEN_IMPERSONATE = (&H4)
Private Const TOKEN_QUERY = (&H8)
Private Const TOKEN_QUERY_SOURCE = (&H10)
Private Const TOKEN_ADJUST_PRIVILEGES = (&H20)
Private Const TOKEN_ADJUST_GROUPS = (&H40)
Private Const TOKEN_ADJUST_DEFAULT = (&H80)
Private Const TOKEN_ALL_ACCESS = (STANDARD_RIGHTS_REQUIRED Or _
                        TOKEN_ASSIGN_PRIMARY Or _
                        TOKEN_DUPLICATE Or _
                        TOKEN_IMPERSONATE Or _
                        TOKEN_QUERY Or _
                        TOKEN_QUERY_SOURCE Or _
                        TOKEN_ADJUST_PRIVILEGES Or _
                        TOKEN_ADJUST_GROUPS Or _
                        TOKEN_ADJUST_DEFAULT)
Private Const TOKEN_READ = (STANDARD_RIGHTS_READ Or _
                        TOKEN_QUERY)
Private Const TOKEN_WRITE = (STANDARD_RIGHTS_WRITE Or _
                        TOKEN_ADJUST_PRIVILEGES Or _
                        TOKEN_ADJUST_GROUPS Or _
                        TOKEN_ADJUST_DEFAULT)
Private Const TOKEN_EXECUTE = (STANDARD_RIGHTS_EXECUTE)

Private Const TokenDefaultDacl = 6
Private Const TokenGroups = 2
Private Const TokenImpersonationLevel = 9
Private Const TokenOwner = 4
Private Const TokenPrimaryGroup = 5
Private Const TokenPrivileges = 3
Private Const TokenSource = 7
Private Const TokenStatistics = 10
Private Const TokenType = 8
Private Const TokenUser = 1
' ============================================================================================

Public Function WinError(ByVal lLastDLLError As Long) As String
Dim sBuff As String
Dim lCount As Long
   
    ' Return the error message associated with LastDLLError:
    sBuff = String$(256, 0)
    lCount = FormatMessage( _
    FORMAT_MESSAGE_FROM_SYSTEM Or FORMAT_MESSAGE_IGNORE_INSERTS, _
    0, lLastDLLError, 0&, sBuff, Len(sBuff), ByVal 0)
    If lCount Then
    WinError = Left$(sBuff, lCount)
    End If
   
End Function

Public Function IsNT() As Boolean
Static bOnce As Boolean
Static bValue As Boolean

    ' Return whether the system is running NT or not:
    If Not (bOnce) Then
    Dim tVI As OSVERSIONINFO
    tVI.dwOSVersionInfoSize = Len(tVI)
    If (GetVersionEx(tVI) <> 0) Then
        bValue = (tVI.dwPlatformId = VER_PLATFORM_WIN32_NT)
        bOnce = True
    End If
    End If
    IsNT = bValue
   
End Function

Private Function NTEnableShutDown(ByRef sMsg As String) As Boolean
Dim tLUID As LUID
Dim hProcess As Long
Dim hToken As Long
Dim tTP As TOKEN_PRIVILEGES, tTPOld As TOKEN_PRIVILEGES
Dim lTpOld As Long
Dim lR As Long

    ' Under NT we must enable the SE_SHUTDOWN_NAME privilege in the
    ' process we're trying to shutdown from, otherwise a call to
    ' try to shutdown has no effect!

    ' Find the LUID of the Shutdown privilege token:
    lR = LookupPrivilegeValue(vbNullString, SE_SHUTDOWN_NAME, tLUID)
   
    ' If we get it:
    If (lR <> 0) Then
               
    ' Get the current process handle:
    hProcess = GetCurrentProcess()
    If (hProcess <> 0) Then
        ' Open the token for adjusting and querying (if we can - user may not have rights):
        lR = OpenProcessToken(hProcess, TOKEN_ADJUST_PRIVILEGES Or TOKEN_QUERY, hToken)
        If (lR <> 0) Then
                   
            ' Ok we can now adjust the shutdown priviledges:
            With tTP
                .PrivilegeCount = 1
                With .Privileges(0)
                .Attributes = SE_PRIVILEGE_ENABLED
                .pLuid.HighPart = tLUID.HighPart
                .pLuid.LowPart = tLUID.LowPart
                End With
            End With
           
            ' Now allow this process to shutdown the system:
            lR = AdjustTokenPrivileges(hToken, 0, tTP, Len(tTP), tTPOld, lTpOld)
           
            If (lR <> 0) Then
                NTEnableShutDown = True
            Else
                Err.Raise eeSSDErrorBase + 6, App.EXEName & ".mShutDown", "Can't enable shutdown: You do not have the privileges to shutdown this system. [" & WinError(Err.LastDllError) & "]"
            End If
           
            ' Remember to close the handle when finished with it:
            CloseHandle hToken
        Else
            Err.Raise eeSSDErrorBase + 6, App.EXEName & ".mShutDown", "Can't enable shutdown: You do not have the privileges to shutdown this system. [" & WinError(Err.LastDllError) & "]"
        End If
    Else
        Err.Raise eeSSDErrorBase + 5, App.EXEName & ".mShutDown", "Can't enable shutdown: Can't determine the current process. [" & WinError(Err.LastDllError) & "]"
    End If
    Else
    Err.Raise eeSSDErrorBase + 4, App.EXEName & ".mShutDown", "Can't enable shutdown: Can't find the SE_SHUTDOWN_NAME privilege value. [" & WinError(Err.LastDllError) & "]"
    End If

End Function

Public Function ShutdownSystem( _
    Optional ByVal eType As EShutDownTypes) As Boolean
Dim lR As Long
Dim sMsg As String

    ' Validate shutdown type:
    If (eType < EShutDownTypes.[_First] And eType > EShutDownTypes.[_Last]) Then
    Err.Raise eeSSDErrorBase + 7, App.EXEName & ".mShutDown", "Invalid parameter to ShutdownSystem: " & eType, vbInformation
    Exit Function
    End If

    ' Make sure we have enabled the privilege to shutdown
    ' for this process if we're running NT:
    If (IsNT) Then
    If Not (NTEnableShutDown(sMsg)) Then
        Exit Function
    End If
    End If

    ' This is the code to shut down
    lR = ExitWindowsEx(eType, &HFFFFFFFF)
    If (lR = 0) Then
    Err.Raise eeSSDErrorBase + 3, App.EXEName & ".mShutDown", "ShutdownSystem failed: " & WinError(Err.LastDllError)
    Else
    ' Remember that shutdown will proceed on another
    ' thread to this one, so code may continue to
    ' execute after this.
    ShutdownSystem = True
End If

End Function

Læg mærke til at det under XP/NT er muligt at en bruger ikke kan opnå rettigheder til at lukke systemet ned. I så fald har ShutdownSystem ingen effekt, og returnerer false. Du kan bruge flg. konstanter som parametre:
0  Log af
1  Luk ned, uden af afbryde strømmen
2  Genstart
8  Luk ned, og afbryd strømmen
Avatar billede jsc Nybegynder
06. november 2003 - 18:03 #5
hvis koden er kortere/lettere i C/C++ så vil jeg gerne have det istedet :)
men jeg kan da lige prøve den metode du har til vb også.. selvom jeg gerne ville have "shutdown -s" fucktionen med fordi jeg ved den virker!

men jeg prøver lige vb-koden også

/jsc
Avatar billede driis Nybegynder
06. november 2003 - 18:13 #6
Samme kode ser således ud i C/C++:
#include <windows.h>

bool ShutDownSystem(long flag)
{
    OSVERSIONINFO        vi ;
    LUID                luid ;
    HANDLE                hProcess, hToken ;
    long                ret = -1 ;
    DWORD                s ;
    TOKEN_PRIVILEGES    tp, tpOld ;

    vi.dwOSVersionInfoSize = sizeof(vi) ;
    GetVersionEx(&vi) ;
    if ( vi.dwPlatformId == VER_PLATFORM_WIN32_NT )
    {
        // Der køres NT, og vi skal have lavet rettigheder til at lukke systemet ned
        if ( LookupPrivilegeValue(0,SE_SHUTDOWN_NAME,&luid) )
        {
            hProcess = GetCurrentProcess()  ;
            if ( hProcess )
            {
                if ( OpenProcessToken(hProcess,TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken) )
                {
                    tp.PrivilegeCount = 1 ;
                    tp.Privileges->Attributes = SE_PRIVILEGE_ENABLED ;
                    tp.Privileges->Luid.HighPart = luid.HighPart ;
                    tp.Privileges->Luid.LowPart = luid.LowPart  ;
                    ret = AdjustTokenPrivileges(hToken, FALSE,&tp,sizeof(tp),&tpOld,&s) ;
                }
                CloseHandle(hToken) ;
            }
        }
    }
   
    if ( ExitWindowsEx(flag,0) )
        return true ;
    else
        return false ;   
}

Samme parametre er mulige.
Avatar billede jsc Nybegynder
06. november 2003 - 18:27 #7
lige en ting til C/C++ koden, hvordan kalder mand en funktion i det?

Call ShutDownSystem(long flag)  ??
Avatar billede jsc Nybegynder
06. november 2003 - 18:40 #8
jeg har nu sat koden ind i mit vb-program, men den logger kun af.. det er et lille problem - det ved jeg, men jeg kan ikke finde det sted hvor der skal laves om til "8" for at lukke maskinen - hvor er det?
Avatar billede jsc Nybegynder
06. november 2003 - 18:44 #9
nevermind.. havde ikke læst koden ordenligt igennem - TAK! det virker nu, så er jeg fri for at kalde "shutdown -s"

men jeg vil stadig gerne lige vide hvordan du kalder funktionen i C/C++..

/jsc
Avatar billede driis Nybegynder
06. november 2003 - 19:04 #10
For at kalde C funktionen fra Visual Basic skal du have compilet koden til en DLL, og derefter kalde funktionen fra denne DLL.
Avatar billede jsc Nybegynder
06. november 2003 - 19:41 #11
det var ikke lige det jeg tænkte på, det var hvis jeg fandt på at lave mit program i C/C++ istedet, hvordan kalder du så funktionen luk funktionen lige som du kan gøre i vb med: "Call funktionsnavn"?
Avatar billede driis Nybegynder
06. november 2003 - 20:56 #12
bare
ShutDownSystem();

f.eks.:

int main()
{
  bool ans = ShutDownSystem(8) ;
  if ( !ans )
  { 
      // der skete en fejl, udskriv evt. noget til brugeren
  }
  return 0;
}
Avatar billede jsc Nybegynder
06. november 2003 - 21:26 #13
okay.. ikke andet.. tak!
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
IT-kurser om Microsoft 365, sikkerhed, personlig vækst, udvikling, digital markedsføring, grafisk design, SAP og forretningsanalyse.

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester