services dtsx sql-server ssis oledb sql-agent

sql server - dtsx - Error de trabajo del Agente SQL con el paquete SSIS para acceder a la base de datos



dtsx sql server 2008 (2)

Tengo un paquete de SSIS que ejecuta una tarea de script (en su mayoría, y algunas otras cosas). La tarea de secuencia de comandos se conecta a una base de datos de Access mediante una conexión OleDB. Esta es la conexión de Microsoft Jet 4.0. Tengo los controladores instalados. Pero no se ejecutará en SQL Agent a través de una cuenta de proxy. Correrá bien directamente desde Visual Studio y desde el almacén de paquetes. De hecho, funciona bien en ambos lugares cuando inicio sesión como la cuenta especial a la que está vinculado el proxy. Pero cuando corro a través del Agente de SQL Server, obtengo el temido "Error no especificado" OleDbException.

Código relevante de la tarea de script:

// class field private string accessConnectionStringTemplate = "Data Source=/"{0}/";Provider=Microsoft.Jet.OLEDB.4.0;"; // in method that connects to database Print(file, "Connection string: " + string.Format(accessConnectionStringTemplate, file.FileName)); // outputs: Data Source = "/Path/To/File";Provider=Microsoft.Jet.OLEDB.4.0" using(access = new OleDbConnection(string.Format(accessConnectionStringTemplate, file.FileName))) { access.Open(); // other code }

Los mensajes de error a través del historial de trabajos del Agente SQL:

Started: 12:35:10 PM Error: 2016-11-03 12:35:33.51 Code: 0x00000000 Source: Import Files Main Description: Exception: Unspecified error End Error Error: 2016-11-03 12:35:33.51 Code: 0x00000000 Source: Import Files Main Description: at System.Data.OleDb.OleDbConnectionInternal..ctor(OleDbConnectionString constr, OleDbConnection connection) at System.Data.OleDb.OleDbConnectionFactory.CreateConnection(DbConnectionOptions options, DbConnectionPoolKey poolKey, Object poolGroupProviderInfo, DbConnectionPool pool, DbConnection owningObject) at System.Data.ProviderBase.DbConnectionFactory.CreateConnection(DbConnectionOptions options, DbConnectionPoolKey poolKey, Object poolGroupProviderInfo, DbConnectionPool pool, DbConnection owningConnection, DbConnectionOptions userOptions) at System.Data.ProviderBase.DbConnectionFactory.CreateNonPooledConnection(DbConnection owningConnection, DbConnectionPoolGroup poolGroup, DbConnectionOptions userOptions) at System.Data.ProviderBase.DbConnectionFactory.TryGetConnection(DbConnection owningConnection, TaskCompletionSource`1 retry, DbConnectionOptions userOptions, DbConnectionInternal oldConnection, DbConnectionInternal& connection) at System.Data.ProviderBase.DbConnectionInternal.TryOpenConnectionInternal(DbConnection outerConnection, DbConnectionFactory connectionFactory, TaskCompletionSource`1 retry, DbConnectionOptions userOptions) at System.Data.ProviderBase.DbConnectionClosed.TryOpenConnection(DbConnection outerConnection, DbConnectionFactory connectionFactory, TaskCompletionSource`1 retry, DbConnectionOptions userOptions) at System.Data.ProviderBase.DbConnectionInternal.OpenConnection(DbConnection outerConnection, DbConnectionFactory connectionFactory) at System.Data.OleDb.OleDbConnection.Open() at ST_cc0028a4b56242909c2eae546a807995.csproj.ScriptMain.ImportFile(AccessFile file, DateTime startRecordDate, DateTime endRecordDate, List`1 accessTables, Boolean includeTransactionTables, List`1 specifiedTableList) at ST_cc0028a4b56242909c2eae546a807995.csproj.ScriptMain.Main() End Error Error: 2016-11-03 12:35:33.51 Code: 0x00000006 Source: Import Files Description: The script returned a failure result. End Error

Algunas cosas de las que me he asegurado:

  • Los controladores de acceso están instalados y funcionan en el servidor en el que está el Agente SQL. Lo verifiqué ejecutando el paquete en VS como mi cuenta y la cuenta del proxy, sin problemas.
  • La cuenta de proxy tiene acceso al archivo en cuestión. De nuevo, verificado al iniciar sesión en el servidor como la cuenta del proxy. El archivo está en una red compartida, pero la ruta se especifica como una ruta UNC.
  • La cuenta de proxy tiene acceso a otras bases de datos que son parte de esta operación, para descartar otras posibles fuentes de error.
  • Ejecutar el paquete desde el almacén de paquetes (a través de SSMS) ya que mi cuenta y la cuenta del proxy funcionan. Hice esto en el servidor de la base de datos para asegurarme.

En otras preguntas que he visto en Internet sobre esto, generalmente es un problema con los controladores. En este caso, no estoy seguro de cómo podría ser.

Me complace proporcionar información adicional para ayudar a otros a diagnosticar. Yo mismo estoy completamente inseguro de por qué esto no está funcionando.


Sugeriría probar algunas cosas:

  1. Intente ejecutar su paquete con el modo cmd, es decir, utilizando la sintaxis dtexce.exe del Agente SQL (utilizando las opciones de 32 bits y 64 bits).

  2. Agregue la cuenta de servicio (Account SQL Agent se está ejecutando) al DCOM component for Integration Service . Si está permitido, cambie la cuenta del Servicio del Agente SQL a la cuenta Proxy (para prueba).

  3. Haga todo lo posible con la cuenta Proxy, es decir, implemente el paquete utilizando la Cuenta Proxy y haga que el propietario del trabajo sea una Cuenta Proxy (en el Agente SQL). Crea el trabajo usando la cuenta Proxy.

  4. Compruebe el event viewer Windows si tiene algún error relacionado con su cuenta de proxy o con la cuenta de servicio de SQL Agent.

  5. Si está utilizando SQL Server 2012 o superior, implemente el paquete, pruébelo con el catálogo de Integration Services.


Resultó que el problema era que el proveedor de Jet intentaba escribir en el directorio temporal del usuario de SQL Agent, aunque la tarea se ejecutaba con personificación como un usuario diferente. Esto parece ser una característica del sistema de suplantación de Windows, que no cambia el perfil del usuario, solo el token del usuario. Terminé con este código:

var tempPath = Path.GetTempPath().Replace("//SQLSERVERAGENT//", "//" + Environment.UserName + "//"); Environment.SetEnvironmentVariable("TEMP", tempPath); Environment.SetEnvironmentVariable("TMP", tempPath);

No es ideal, pero funciona. Significa que no tengo que dar permisos al directorio temporal del Agente SQL. Solo este código tiene que cambiar.

Lamentablemente, parece que no hay forma de cambiar el lugar donde el controlador ODBC coloca sus archivos temporales.

EDITAR: También tuve este problema con un paquete regular basado en flujo de datos con una fuente de Excel. En ese caso, no tuve más remedio que otorgar acceso al directorio temporal del agente de SQL para la cuenta de mi usuario proxy. Si puedo encontrar una solución allí también, la publicaré.