Como implantar o SQL Server Compact Edition 4.0?
Como faço para implantar o Microsoft SQL Server Compact 4.0 ?
a edição compacta do servidor SQL (actualmente na versão 4.0) é:
Mas como é que o implantamos?um banco de dados livre e embutido que os programadores de software podem usar para construir aplicações de desktop Windows. Ele tem uma pequena pegada e suporta a implantação privada de seus binários dentro da pasta de Aplicação.
- a Microsoft diz que pode ser implantado na pasta de Aplicação (bom ) e suporta a implementação do xcopy .
- a Microsoft também diz que não pode ser implantado dentro da pasta de Aplicação ( mau ), e não suporta a implementação xcopy . Algumas pessoas têm exemplos disso usando um xcopy simples, mas não entram nos detalhes necessários para completar a implantação
o problema é que não pode usar o fornecedor de Ado OLEdb a menos que esteja registado. O registo de um fornecedor OLEdb tem de ser feito como administrador. Isso significa que o SQL Server Compact edition irá falhar com usuários que não são um administrador.
O Compact 4.0 do servidor SQL vem com um ficheiro redist_enu.txt
:
a lista .ficheiros exe cada um instala os seus componentes fechados num local específico no computador de destino. Isto ajuda a garantir a utilização e o apoio técnico. O .os ficheiros dll incluídos nestes .os ficheiros exe também estão disponíveis separadamente neste redist.txt. No entanto, distribuições destes separado .dlls pode resultar em problemas de Utilização. Para mais detalhes, consulte http://go.microsoft.com/fwlink/?LinkId=94589
detecção de implantação privada através de uma plataforma: implantação privada apenas da pilha nativa e carregamento explícito do conjunto compacto do servidor SQL via montagem.Load from (),.o arquivo local, ou o uso de estratégias de redirecionamento DLL/COM não são suportados e podem resultar em utilização problema. Para mais informações, ver http://support.microsoft.com/kb/835322 e http://msdn2.microsoft.com/en-us/library/aa375142.aspx
Microsoft SQL Server Compact 4.0
SSCERuntime_x86-ENU.exe
SSCERuntime_x86-Deus.exe
SSCERuntime_x86-FRA.exe
SSCERuntime_x86-JPN.exe
SSCERuntime_x86-RUS.exe
SSCERuntime_x86-ESN.exe
SSCERuntime_x86-ITA.exe
SSCERuntime_x86-KOR.exe
SSCERuntime_x86-CHT.exe
SSCERuntime_x86-CHS.exe
SSCERuntime_x64-ENU.exe
SSCERuntime_x64-DEU.exe
SSCERuntime_x64-FRA.exe
SSCERuntime_x64-JPN.exe
SSCERuntime_x64-RUS.exe
SSCERuntime_x64-ESN.exe
SSCERuntime_x64-ITA.exe
SSCERuntime_x64-KOR.exe
SSCERuntime_x64-CHT.exe
SSCERuntime_x64-CHS.exe
sqlcese40.dll
sqlceqp40.dll
sqlceoledb40.dll
sqlceca40.dll
sqlceme40.dll
sqlcecompact40.dll
sqlceer40en.dll
sqlceer40cn.dll / sqlceer40zh-CHS.dll
sqlceer40de.dll
sqlceer40es.dll
sqlceer 40FR.dll
sqlceer40it.dll
sqlceer40ja.dll
sqlceer40ko.dll
sqlceer 40tw.dll / sqlceer40zh-CHT.dll
sqlceer40ru.dll
Sistema.Dado.SqlServerCe.dll
Sistema.Dado.SqlServerCe.Entidade.dll
mas não dá nenhuma informação sobre como redistribuir o compacto do servidor SQL 4.0.
a espelhar aleatoriamente a pasta não documentada Program Files
encontrei 7 dlls:
C:\Program Files\Microsoft SQL Server Compact Edition\v4.0\
sqlceoledb40.dll
sqlceqp40.dll
sqlcese40.dll
sqlceca40.dll
sqlcecompact40.dll
sqlceer40EN.dll
sqlceme40.dll
nota: existem também algumas pastas-filhos com mais dlls
tentei copiar estes 7 dll's para uma pasta, e tentei abrir uma ligação ado usando o texto de ligação:
Provider=Microsoft.SQLSERVER.CE.OLEDB.4.0;Data Source="store.sdf"
Mas falha com 0x80004005 Unspecified error
2 answers
A edição compacta do servidor SQL é composta por 7 dlls:
-
sqlceme40.dll
a biblioteca API plana e não documentada (o conjunto. netSystem.Data.SqlServerCe.dll
é um invólucro em torno deste dll) -
sqlceca40.dll
uma comissão que implementaEngine
,Replication
,Error
e alguns outros objectos COM -
sqlceoledb40.dll
um com dll que implementa um fornecedor de OLEdb para o SCE (permitindo a utilização de ADO) -
sqlcese40.dll
desconhecido -
sqlceqp40.dll
desconhecido -
sqlcecompact40.dll
desconhecido -
sqlceer40en.dll
desconhecido
>regsvr32 sqlceca40.dll
>regsvr32 sqlceoledb40.dll
O problema é que o registo de um objecto COM requerprivilégios administrativos (usando uma solução global para resolver um problema local ). Isto significa que os seus utilizadores
- tem de instalar a sua aplicação (que não quer fazer)
- exige que os seus utilizadores tenham permissões administrativas (o que não quer fazer)
Felizmente, a partir de 2001 com o Windows XP, a Microsoft resolveu este problema comum: sem registo COM.
Primeiro, declarará que o seu pedido tem um "dependência" on SQL Server Compact Edition 4.0. Você faz isso escrevendo um manifesto da Assembléia:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<assemblyIdentity
version="1.0.0.0"
processorArchitecture="X86"
name="client"
type="win32"
/>
<description>Hyperion Pro</description>
<!-- We have a dependancy on SQL Server CE 4.0 -->
<dependency>
<dependentAssembly>
<assemblyIdentity
type="win32"
name="Microsoft.SQLSERVER.CE.4.0"
version="4.0.0.0" processorArchitecture="x86"
/>
</dependentAssembly>
</dependency>
<!-- We are high-dpi aware on Windows Vista -->
<asmv3:application xmlns:asmv3="urn:schemas-microsoft-com:asm.v3">
<asmv3:windowsSettings
xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">
<dpiAware>true</dpiAware>
</asmv3:windowsSettings>
</asmv3:application>
<!-- We were designed and tested on Windows 7 -->
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
<application>
<!--The ID below indicates application support for Windows 7 -->
<supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>
<!--The ID below indicates application support for Windows Vista -->
<!--supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"/-->
</application>
</compatibility>
<!-- Disable file and registry virtualization -->
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
<security>
<requestedPrivileges>
<requestedExecutionLevel level="asInvoker" uiAccess="false"/>
</requestedPrivileges>
</security>
</trustInfo>
</assembly>
Pode colocar este ficheiro ao lado de o seu executável (como Hyperion.exe.manifest
), ou pode construí-lo na sua aplicação como um recurso RT_MANIFEST
.
Microsoft.SQLSERVER.CE.4.0
. Nós criamos esta montagem primeiro criando um diretório chamado:
Quando colocares a tua candidatura, colocarás todos os 7 dll's que compõem isto. "montagem" nesta subpastaMicrosoft.SQLSERVER.CE.4.0
Microsoft.SQLSERVER.CE.4.0
, juntamente com um ficheiro especial .manifest
:
C:\
|---Users
|---Ian
|---AppData
|---Local
|---Hyperion Pro
| Hyperion.exe
| Hyperion.exe.manifest
|----Microsoft.SQLSERVER.CE.4.0
sqlceme40.dll
sqlceca40.dll
sqlceoledb40.dll
sqlcese40.dll
sqlceqp40.dll
sqlcecompact40.dll
sqlceer40en.dll
Microsoft.SQLSERVER.CE.4.0.manifest
Por outras palavras, a pasta de aplicação contém a sua aplicação e a Microsoft.SQLSERVER.CE.4. 0 pasta:
Directory of C:\Users\Ian\AppData\Local\Hyperion Pro
05/29/2012 09:23 AM 1,899,008 Hyperion.exe
05/28/2012 01:46 PM 1,587 Hyperion.exe.manifest
05/29/2012 09:27 AM <DIR> Microsoft.SQLSERVER.CE.4.0
2 File(s) 1,900,675 bytes
1 Dir(s) 20,851,503,104 bytes free
A próxima parte da sua tarefa é definir o ficheiro Microsoft.SQLSERVER.CE.4.0.manifest
. A com livre de registo permite que um ficheiro Manifesto declare todos os objectos COM e os seus clsid. isto exigiu muita engenharia reversa. Mas o manifesto de montagem para a edição compacta do servidor SQL 4.0 riz:
Microsoft.SQLSERVER.CE.4.0.Manifesto:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<assemblyIdentity
type="win32"
name="Microsoft.SQLSERVER.CE.4.0"
processorArchitecture="x86"
version="4.0.0.0" />
<!-- OLEDB Provider -->
<file name = "sqlceoledb40.dll">
<comClass
description = "Microsoft SQL Server Compact OLE DB Provider for Windows"
clsid="{2006C53A-C915-41EA-BAA9-9EAB3A1FBF97}"
threadingModel = "Both"
progid = "Microsoft.SQLSERVER.CE.OLEDB.4.0" />
</file>
<!-- Native flat engine library -->
<file name="sqlceme40.dll" />
<!-- Engine and Replication COM object -->
<file name="sqlceca40.dll">
<comClass description="Active SSCE Engine Object"
clsid="{68D45319-3702-4837-9F8E-DA6845D82482}"
threadingModel="Both"
progid="SSCE.Engine.4.0" />
<comClass description="SSCE Error Object"
clsid="{36228F21-B5C7-4054-8DC2-47D3E236E8B5}"
threadingModel="Both"
progid="SSCE.Error.4.0" />
<comClass description="SSCE Param Object"
clsid="{0B3A7B75-A9B0-4580-9AA5-1A7DA47AD1CB}"
threadingModel="Both"
progid="SSCE.Param.4.0" />
<comClass description="Active SSCE Replication Object"
clsid="{11D5B2D4-26A4-44F5-A48B-0FAC3A919ED8}"
threadingModel="Both"
progid="SSCE.Replication.4.0" />
<comClass description="Active SSCE remote data access Object"
clsid="{58BC9AD6-BF11-40B3-9AB1-E3F2ED784C08}"
threadingModel="Both"
progid="SSCE.RemoteDataAccess.4.0" />
<typelib tlbid="{CE4AACFA-3CFD-4028-B2D9-F272314F07C8}"
version="4.0"
helpdir=""/>
</file>
<comInterfaceExternalProxyStub
name="ISSCEEngine"
iid="{10EC3E45-0870-4D7B-9A2D-F4F81B6B7FA2}"
proxyStubClsid32="{00020424-0000-0000-C000-000000000046}"
baseInterface="{00000000-0000-0000-C000-000000000046}"
tlbid = "{CE4AACFA-3CFD-4028-B2D9-F272314F07C8}" />
<comInterfaceExternalProxyStub
name="ISSCEError"
iid="{31155A3B-871D-407F-9F73-DEBFAC7EFBE3}"
proxyStubClsid32="{00020424-0000-0000-C000-000000000046}"
baseInterface="{00000000-0000-0000-C000-000000000046}"
tlbid = "{CE4AACFA-3CFD-4028-B2D9-F272314F07C8}" />
<comInterfaceExternalProxyStub
name="ISSCERDA"
iid="{4F04F79D-1FF1-4DCD-802B-3D51B9356C14}"
proxyStubClsid32="{00020424-0000-0000-C000-000000000046}"
baseInterface="{00000000-0000-0000-C000-000000000046}"
tlbid = "{CE4AACFA-3CFD-4028-B2D9-F272314F07C8}" />
<comInterfaceExternalProxyStub
name="ISSCEParams"
iid="{A78AFF90-049C-41EC-B1D8-665968AAC4A6}"
proxyStubClsid32="{00020424-0000-0000-C000-000000000046}"
baseInterface="{00000000-0000-0000-C000-000000000046}"
tlbid = "{CE4AACFA-3CFD-4028-B2D9-F272314F07C8}" />
<comInterfaceExternalProxyStub
name="ISSCEParam"
iid="{A9876C60-2667-44E5-89DB-E9A46ED392C0}"
proxyStubClsid32="{00020424-0000-0000-C000-000000000046}"
baseInterface="{00000000-0000-0000-C000-000000000046}"
tlbid = "{CE4AACFA-3CFD-4028-B2D9-F272314F07C8}" />
<comInterfaceExternalProxyStub
name="ISSCEErrors"
iid="{C40143CA-E9F9-4FF4-B8B4-CC02C064FC1B}"
proxyStubClsid32="{00020424-0000-0000-C000-000000000046}"
baseInterface="{00000000-0000-0000-C000-000000000046}"
tlbid = "{CE4AACFA-3CFD-4028-B2D9-F272314F07C8}" />
<comInterfaceExternalProxyStub
name="ISSCEMerge"
iid="{C6EB397F-D585-428D-A4F4-454A1842CB47}"
proxyStubClsid32="{00020424-0000-0000-C000-000000000046}"
baseInterface="{00000000-0000-0000-C000-000000000046}"
tlbid = "{CE4AACFA-3CFD-4028-B2D9-F272314F07C8}" />
<file name="sqlceqp40.dll" />
<file name="sqlcese40.dll" />
<file name="sqlcecompact40.dll" />
<file name="sqlceer40EN.dll" />
</assembly>
A última gotcha é que, da mesma forma que temos uma dependência de um conjunto chamado Microsoft.SQLSERVER.CE.4.0
, o SQL Server Compact Edition 4.0, por sua vez, tem uma dependência de um conjunto chamado Microsoft.VC90.CRT
. Felizmente a sua instalação de naves SQLCE com uma cópia deste conjunto:
|----Microsoft.VC90.CRT
| Microsoft.VC90.CRT.manifest
| msvcr90.dll
Isto significa que a estrutura final das pastas é:
C:\
|---Users
|---Ian
|---AppData
|---Local
|---Hyperion Pro
| Hyperion.exe
| Hyperion.exe.manifest
|----Microsoft.SQLSERVER.CE.4.0
| Microsoft.SQLSERVER.CE.4.0.manifest
| sqlceme40.dll
| sqlceca40.dll
| sqlceoledb40.dll
| sqlcese40.dll
| sqlceqp40.dll
| sqlcecompact40.dll
| sqlceer40en.dll
|---Microsoft.VC90.CRT
| Microsoft.VC90.CRT.manifest
| msvcr90.dll
Para o servidor de Sql Ce 4.0 SP1:
Em vez de abordar todas as coisas importantes da implantação, optei por incluir os próprios ficheiros de configuração na minha exe como fonte incorporada e fiz este pequeno ajudante:
public static class RedistHelper
{
private static readonly ILog Log = LogManager.GetLogger(
MethodBase.GetCurrentMethod().DeclaringType);
private static readonly string SqlCeRedistName64 = "SSCERuntime_x64-ENU.exe";
private static readonly string SqlCeRedistName32 = "SSCERuntime_x86-ENU.exe";
private static readonly Dictionary<string, Assembly> Assemblies =
new Dictionary<string, Assembly>(StringComparer.OrdinalIgnoreCase);
private static string SqlCeRedistName
{
get
{
return Environment.Is64BitOperatingSystem
? SqlCeRedistName64
: SqlCeRedistName32;
}
}
public static bool IsSqlCeInstalled()
{
RegistryKey localKey = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine,
RegistryView.Registry64);
RegistryKey ret = localKey.OpenSubKey(
@"SOFTWARE\Microsoft\Microsoft SQL Server Compact Edition\v4.0\ENU");
return ret != null;
}
private static byte[] ReadFully(Stream input)
{
byte[] buffer = new byte[16 * 1024];
using (MemoryStream ms = new MemoryStream())
{
int read;
while ((read = input.Read(buffer, 0, buffer.Length)) > 0)
ms.Write(buffer, 0, read);
return ms.ToArray();
}
}
public static Assembly OnCurrentDomainOnAssemblyResolve(object sender,
ResolveEventArgs args)
{
Assembly dll;
var name = new AssemblyName(args.Name).Name + ".dll";
if (!Assemblies.TryGetValue(name, out dll))
{
Assembly res = typeof(RedistHelper).Assembly;
using (Stream input =
res.GetManifestResourceStream(typeof(RedistHelper), name))
{
if (input == null)
{
Log.WarnFormat("Assembly {0} does not contain {1}", res, name);
return null;
}
dll = Assembly.Load(ReadFully(input));
if (dll == null)
{
Log.WarnFormat("Assembly {0} failed to load.", name);
return null;
}
Log.InfoFormat("Loaded assembly {0}.", name);
Assemblies[name] = dll;
return dll;
}
}
return dll;
}
public static void InstallSqlCe()
{
using (Stream stream =
typeof(RedistHelper).Assembly.GetManifestResourceStream(
typeof(RedistHelper), SqlCeRedistName))
{
Debug.Assert(stream != null);
byte[] bytes = new byte[(int)stream.Length];
stream.Read(bytes, 0, bytes.Length);
string path = Path.Combine(Path.GetTempPath(), SqlCeRedistName);
if (File.Exists(path))
File.Delete(path);
File.WriteAllBytes(path, bytes);
Process process = new Process
{
StartInfo = new ProcessStartInfo
{
FileName = path,
UseShellExecute = true
}
};
process.Start();
process.WaitForExit();
}
}
}
A única coisa que me deu dores de cabeça foi referenciar o sistema.Dado.SqlServerCe.dll-ele simplesmente não iria IlMerge, então em vez disso eu carreguei - o sob Demanda, no meu principal:
AppDomain.CurrentDomain.AssemblyResolve += RedistHelper.OnCurrentDomainOnAssemblyResolve;