2016-12-06 111 views
2

我寫了一個簡單的接口到SQL SMO庫,所以我可以停止並從Inno安裝腳本安裝過程中啓動SQL Server。我的開發機器是一個64位處理器機器。託管代碼使用DllExport for .Net以Visual Basic編寫,面向.NET 4.0並針對x86平臺進行編譯。我正在使用Inno Setup 5.5.9 Unicode版本。Inno安裝.NET DLL調用工作在64位,失敗32位

安裝可執行文件在我的開發機器和其他我試過的64位處理器上工作正常。當我運行一個32位處理器系統上的可執行我得到一個錯誤:

External Exception E0434352

這是非常無益的和通用的。這兩個系統都是Windows 10,但是我也嘗試過在其他Windows版本上使用它,並且64位版本和32位版本都沒有。那麼我做了什麼來阻礙32位的運行呢?

Inno Setup的代碼:

[Files] 
Source: "fiSqlSmoLib2\bin\x86\Debug\fiSqlSmoLib2.dll"; DestDir: "{app}"; \ 
    Flags: nocompression 32bit 

[Code] 

function StartSql(machineName, sqlServerName: AnsiString): Integer; 
external '[email protected]:fiSqlSmoLib2.dll stdcall setuponly delayload'; 

function StopSql(machineName, sqlServerName: AnsiString): Integer; 
external '[email protected]:fiSqlSmoLib2.dll stdcall setuponly delayload'; 

function InitializeSetup(): Boolean; 
var 
    SQLresultCode : Integer; 
    Computer : String; 
    SQLServer : String; 
begin 
    Computer := GetComputerNameString; 
    SQLServer := 'FACTORYINSITE'; 

    try 
    SQLresultCode := StopSql(Computer, SQLServer); 
    except 
    ShowExceptionMessage; 
    exit; 
    end; 
    try 
    SQLresultCode := StartSql(Computer, SQLServer); 
    except 
    ShowExceptionMessage; 
    exit; 
    end; 
end; 

Visual Basic代碼:

Imports System.Runtime.InteropServices 
Imports Microsoft.SqlServer.Management.Smo 
Imports Microsoft.SqlServer.Management.Common 
Imports Microsoft.SqlServer.Management.Smo.Wmi 
Imports RGiesecke.DllExport 

Public Class fiSqlSmo 

    <DllExport("StartSql", CallingConvention.StdCall)> _ 
    Public Shared Function StartSql(<MarshalAs(UnmanagedType.LPStr)> machineName As String, <MarshalAs(UnmanagedType.LPStr)> sqlServerName As String) As Integer 
     Dim mc As ManagedComputer 
     Dim Svc As Service 
     Dim svcState As ServiceState 
     Try 
      mc = New ManagedComputer(machineName) 
      Svc = mc.Services("MSSQL$" + sqlServerName) 
     Catch ex As Exception 
      Return ServiceState.Unknown 
     End Try 
     Try 
      svcState = Svc.ServiceState 
     Catch ex As Exception 
      Return ServiceState.Unknown 
     End Try 
     If (Svc.ServiceState <> ServiceState.Running) Then 
      Svc.Start() 
     End If 
     Return svcState 
    End Function 

    <DllExport("StopSql", CallingConvention.StdCall)> _ 
    Public Shared Function StopSql(<MarshalAs(UnmanagedType.LPStr)> machineName As String, <MarshalAs(UnmanagedType.LPStr)> sqlServerName As String) As Integer 
     Dim mc As ManagedComputer 
     Dim Svc As Service 
     Dim svcState As ServiceState 
     Try 
      mc = New ManagedComputer(machineName) 
      Svc = mc.Services("MSSQL$" + sqlServerName) 
     Catch ex As Exception 
      Return ServiceState.Unknown 
     End Try 
     Try 
      svcState = Svc.ServiceState 
     Catch ex As Exception 
      Return ServiceState.Unknown 
     End Try 
     If (Svc.ServiceState = ServiceState.Running) Then 
      Svc.Stop() 
     End If 
     Return svcState 
    End Function 
End Class 
+1

我很確定默認情況下沒有安裝SMO,它在失敗的機器上可用嗎?你的代碼是否在這些機器上的控制檯應用程序中工作?您不需要SMO來啓動/停止MSSQL服務,您可以簡單地使用「ServiceController」或通過[使用Pascal Script]刪除任何.Net依賴項(http://stackoverflow.com/questions/2456987/upgrading-windows-service- using-inno-setup) –

+0

或者嘗試在VB.NET代碼中捕獲並記錄任何異常以調試問題。 –

+0

我相信SMO安裝在測試機器上,但這是一個很好的建議來檢查。我也會嘗試一個控制檯應用程序。 SQL服務器將與安裝程序代碼不同,或者可能位於Azure上,因此我認爲SMO可能是最好的方法。在完整安裝中,我還登錄到SQL服務器並運行腳本,這就是爲什麼我需要確保它正在運行。 – jphoekstra

回答

1

這個問題似乎是使用SMO程序集的版本。該工作的安裝程序與SMO的2016版SMO鏈接,而其失敗的機器僅安裝了SQL 2008 R2。舊版本的機器似乎是巧合的,只有32位。

重建.NET代碼以引用最老的SMO版本會導致它在所有機器上都能正常工作。