2011-07-01 92 views
2

我嘗試使用Inno Setup的Pascal腳本語言來設置服務的失敗操作。我收到經典的「訪問衝突地址...」錯誤。看起來這是不可能的,因爲語言對指針沒有任何支持。有任何想法嗎?以下是代碼片段:使用Inno安裝程序Windows DLL函數調用指針結構

type 
    TScAction = record 
    aType1 : Longword; 
    Delay1 : Longword; 
    aType2 : Longword; 
    Delay2 : Longword; 
    aType3 : Longword; 
    Delay3 : Longword; 
    end; 

type 
    TServiceFailureActionsA = record 
    dwResetPeriod : DWORD; 
    pRebootMsg : String; 
    pCommand : String; 
    cActions : DWORD; 
    saActions : TScAction; 
    end; 

function ChangeServiceConfig2(hService: Longword; dwInfoLevel: Longword; lpInfo: TServiceFailureActionsA): BOOL; 
    external '[email protected] stdcall'; 

procedure SimpleChangeServiceConfig(AService: string); 
var 
    SCMHandle: Longword; 
    ServiceHandle: Longword; 
    sfActions: TServiceFailureActionsA; 
    sActions: TScAction; 
begin 
    try 
    SCMHandle := OpenSCManager('', '', SC_MANAGER_ALL_ACCESS); 
    if SCMHandle = 0 then 
     RaiseException('[email protected]: ' + AService + ' ' + 
     SysErrorMessage(DLLGetLastError)); 
    try 
     ServiceHandle := OpenService(SCMHandle, AService, SERVICE_ALL_ACCESS); 
     if ServiceHandle = 0 then 
     RaiseException('[email protected]: ' + AService + ' ' + 
      SysErrorMessage(DLLGetLastError)); 
     try 

     sActions.aType1 := SC_ACTION_RESTART; 
     sActions.Delay1 := 60000;    // First.nDelay: in milliseconds, MMC displayed in minutes 
     sActions.aType2 := SC_ACTION_RESTART; 
     sActions.Delay2 := 60000; 
     sActions.aType3 := SC_ACTION_RESTART; 
     sActions.Delay3 := 60000; 

     sfActions.dwResetPeriod := 1;   // in seconds, MMC displayes in days 
     //sfActions.pRebootMsg := null;   // reboot message unchanged 
     //sfActions.pCommand := null;   // command line unchanged 
     sfActions.cActions := 3;    // first, second and subsequent failures 
     sfActions.saActions := sActions;   

     if not ChangeServiceConfig2(
      ServiceHandle,      // handle to service 
      SERVICE_CONFIG_FAILURE_ACTIONS,  // change: description 
      sfActions)       // new description 
     then 
      RaiseException('[email protected]: ' + AService + ' ' + 
      SysErrorMessage(DLLGetLastError)); 
     finally 
     if ServiceHandle <> 0 then 
      CloseServiceHandle(ServiceHandle); 
     end; 
    finally 
     if SCMHandle <> 0 then 
     CloseServiceHandle(SCMHandle); 
    end; 
    except 
    ShowExceptionMessage; 
    end; 
end; 
+0

錯誤發生在哪裏? (Inno有一個內置的調試器) 至於訪問違規,當然可能調用外部代碼。 – Deanna

+0

它在調用ChangeServiceConfig2時發生 –

+1

您傳遞的值是什麼?我們不是精神病患者,你需要給我們一些信息繼續下去。 – Deanna

回答

0

嘗試var關鍵字在聲明中lpInfo參數指定,它是一個指針傳遞到結構到功能。

+0

這個工作適合你嗎?如果是這樣,請標記爲已接受。 – Deanna

4

你的腳本有兩個問題。像Deanna建議您必須在參數lpInfo的聲明中使用var關鍵字。

此外,您還需要將TScAction類型更改爲具有兩個元素的數組。

這是我的腳本,您可以將其包含在您的Inno Setup腳本中。

const 
    SERVICE_CONFIG_DELAYED_AUTO_START_INFO = 3; //The lpInfo parameter is a pointer to a SERVICE_DELAYED_AUTO_START_INFO structure. 
               //Windows Server 2003 and Windows XP: This value is not supported. 
    SERVICE_CONFIG_DESCRIPTION    = 1; //The lpInfo parameter is a pointer to a SERVICE_DESCRIPTION structure. 
    SERVICE_CONFIG_FAILURE_ACTIONS   = 2; //The lpInfo parameter is a pointer to a SERVICE_FAILURE_ACTIONS structure. 
               //If the service controller handles the SC_ACTION_REBOOT action, the caller must have 
               // the SE_SHUTDOWN_NAME privilege. For more information, see Running with Special Privileges. 
    SERVICE_CONFIG_FAILURE_ACTIONS_FLAG  = 4; //The lpInfo parameter is a pointer to a SERVICE_FAILURE_ACTIONS_FLAG structure. 
               //Windows Server 2003 and Windows XP: This value is not supported. 
    SERVICE_CONFIG_PREFERRED_NODE   = 9; //The lpInfo parameter is a pointer to a SERVICE_PREFERRED_NODE_INFO structure. 
               //Windows Server 2008, Windows Vista, Windows Server 2003, and Windows XP: This value is not supported. 
    SERVICE_CONFIG_PRESHUTDOWN_INFO   = 7; //The lpInfo parameter is a pointer to a SERVICE_PRESHUTDOWN_INFO structure. 
               //Windows Server 2003 and Windows XP: This value is not supported. 
    SERVICE_CONFIG_REQUIRED_PRIVILEGES_INFO = 6; //The lpInfo parameter is a pointer to a SERVICE_REQUIRED_PRIVILEGES_INFO structure. 
               //Windows Server 2003 and Windows XP: This value is not supported. 
    SERVICE_CONFIG_SERVICE_SID_INFO   = 5; //The lpInfo parameter is a pointer to a SERVICE_SID_INFO structure. 
    SERVICE_CONFIG_TRIGGER_INFO    = 8; //The lpInfo parameter is a pointer to a SERVICE_TRIGGER_INFO structure. 
               //This value is not supported by the ANSI version of ChangeServiceConfig2. 
               //Windows Server 2008, Windows Vista, Windows Server 2003, and Windows XP: This value is not supported until Windows Server 2008 R2. 

    SC_ACTION_NONE  = 0; // No action. 
    SC_ACTION_REBOOT  = 2; // Reboot the computer. 
    SC_ACTION_RESTART  = 1; // Restart the service. 
    SC_ACTION_RUN_COMMAND = 3; // Run a command. 

type 
    TScAction = record 
    aType1 : Longword; 
    Delay1 : Longword; 
    end; 

type 
    TServiceFailureActionsA = record 
    dwResetPeriod : DWORD; 
    pRebootMsg : String; 
    pCommand : String; 
    cActions : DWORD; 
    saActions : array of TScAction; 
    end; 

function ChangeServiceConfig2(
    hService: Longword; 
    dwInfoLevel: Longword; 
    var lpInfo: TServiceFailureActionsA): BOOL; 
    external '[email protected] stdcall'; 


procedure SimpleChangeServiceConfig(AService: string); 
var 
    SCMHandle: Longword; 
    ServiceHandle: Longword; 
    sfActions: TServiceFailureActionsA; 
    sActions: array of TScAction; 
begin 
    SetArrayLength(sActions ,3); 
    try 
    SCMHandle := OpenSCManager('', '', SC_MANAGER_ALL_ACCESS); 
    if SCMHandle = 0 then 
     RaiseException('[email protected]: ' + AService + ' ' + 
     SysErrorMessage(DLLGetLastError)); 
    try 
     ServiceHandle := OpenService(SCMHandle, AService, SERVICE_ALL_ACCESS); 
     if ServiceHandle = 0 then 
     RaiseException('[email protected]: ' + AService + ' ' + 
      SysErrorMessage(DLLGetLastError)); 
     try 

     sActions[0].aType1 := SC_ACTION_RESTART; 
     sActions[0].Delay1 := 60000;    // First.nDelay: in milliseconds, MMC displayed in minutes 
     sActions[1].aType1 := SC_ACTION_RESTART; 
     sActions[1].Delay1 := 60000; 
     sActions[2].aType1 := SC_ACTION_NONE; 
     sActions[2].Delay1 := 60000; 

     sfActions.dwResetPeriod := 1;   // in seconds, MMC displayes in days 
     //sfActions.pRebootMsg := null;   // reboot message unchanged 
     //sfActions.pCommand := null;   // command line unchanged 
     sfActions.cActions := 3;    // first, second and subsequent failures 
     sfActions.saActions := sActions;   

     if not ChangeServiceConfig2(
      ServiceHandle,    // handle to service 
      SERVICE_CONFIG_FAILURE_ACTIONS, // change: description 
      sfActions)  // new description 
     then 
      RaiseException('[email protected]: ' + AService + ' ' + 
      SysErrorMessage(DLLGetLastError)); 
     finally 
     if ServiceHandle <> 0 then 
      CloseServiceHandle(ServiceHandle); 
     end; 
    finally 
     if SCMHandle <> 0 then 
     CloseServiceHandle(SCMHandle); 
    end; 
    except 
    ShowExceptionMessage; 
    end; 
end;  
相關問題