Was ist die beste Methode, um zu überprüfen, ob eine Datei aus einer gespeicherten SQL Server 2005-Prozedur vorhanden ist?

StackOverflow https://stackoverflow.com/questions/16634

  •  08-06-2019
  •  | 
  •  

Frage

Wir haben jahrelang die „undokumentierte“ gespeicherte Prozedur xp_fileexist in SQL Server 2000 verwendet und hatten keine Probleme damit.Im Jahr 2005 wurde das Verhalten offenbar leicht geändert, um immer eine 0 zurückzugeben, wenn das ausführende Benutzerkonto kein Systemadministrator ist.Es scheint auch eine Null zurückzugeben, wenn der SQL Server-Dienst unter dem LocalSystem-Konto ausgeführt wird und Sie versuchen, eine Datei im Netzwerk zu überprüfen.

Ich würde gerne von xp_fileexist wegkommen.Hat jemand eine bessere Möglichkeit, innerhalb einer gespeicherten Prozedur das Vorhandensein einer Datei an einem Netzwerkspeicherort zu überprüfen?

War es hilfreich?

Lösung

Vielleicht ist eine gespeicherte CLR-Prozedur genau das, wonach Sie suchen.Diese werden im Allgemeinen verwendet, wenn Sie auf irgendeine Weise mit dem System interagieren müssen.

Andere Tipps

Sie müssen die CLR als EXTERNAL_ACCESS markieren, um Zugriff auf den System.IO-Namespace zu erhalten. Im weiteren Verlauf ist das jedoch keine schlechte Vorgehensweise.

SAFE ist der Standardberechtigungssatz, der jedoch sehr restriktiv ist.Mit der SAFE-Einstellung können Sie nur auf Daten aus einer lokalen Datenbank zugreifen, um Berechnungslogik für diese Daten auszuführen.EXTERNAL_ACCESS ist der nächste Schritt in der Berechtigungshierarchie.Mit dieser Einstellung können Sie auf externe Ressourcen wie das Dateisystem, die Windows-Ereignisanzeige und Webdienste zugreifen.Diese Art des Ressourcenzugriffs ist in SQL Server 2000 und früheren Versionen nicht möglich.Dieser Berechtigungssatz schränkt auch Vorgänge wie den Zeigerzugriff ein, die sich auf die Robustheit Ihrer Assembly auswirken.Der UNSAFE-Berechtigungssatz setzt volle Vertrauenswürdigkeit der Assembly voraus und erlegt daher keine Einschränkungen der „Codezugriffssicherheit“ auf.Diese Einstellung ist vergleichbar mit der Funktionsweise erweiterter gespeicherter Prozeduren – Sie gehen davon aus, dass der gesamte Code sicher ist.Allerdings beschränkt diese Einstellung die Erstellung unsicherer Assemblys auf Benutzer mit Systemadministratorberechtigungen.Microsoft empfiehlt, die Erstellung unsicherer Assemblys so weit wie möglich zu vermeiden.

Ich glaube immer noch, dass ein CLR-Verfahren die beste Lösung sein könnte.Also akzeptiere ich diese Antwort.Aber entweder bin ich nicht so schlau oder es ist extrem schwierig umzusetzen.Unser SQL Server-Dienst läuft unter einem lokalen Konto, da dies laut Mircosoft die einzige Möglichkeit ist, einen iSeries-Verbindungsserver von einer 64-Bit-SQL Server 2005-Instanz aus zum Laufen zu bringen.Wenn wir den SQL Server-Dienst so ändern, dass er mit einem Domänenkonto ausgeführt wird, funktioniert der Befehl xp_fileexist einwandfrei für Dateien im Netzwerk.

Ich habe diese gespeicherte CLR-Prozedur erstellt und sie mit der Berechtigungsstufe „Extern“ erstellt und signiert:

using System;
using System.Data;
using System.Data.SqlClient;
using System.Data.SqlTypes;
using Microsoft.SqlServer.Server;
using System.Security.Principal;

public partial class StoredProcedures
{
    [Microsoft.SqlServer.Server.SqlProcedure]
    public static void FileExists(SqlString fileName, out SqlInt32 returnValue)
    {
        WindowsImpersonationContext originalContext = null;

        try
        {
            WindowsIdentity callerIdentity = SqlContext.WindowsIdentity;
            originalContext = callerIdentity.Impersonate();

            if (System.IO.File.Exists(Convert.ToString(fileName)))
            {
                returnValue = 1;
            }
            else
            {
                returnValue = 0;
            }
        }
        catch (Exception)
        {
            returnValue = -1;
        }
        finally
        {
            if (originalContext != null)
            {
                originalContext.Undo();
            }
        }
    }
}

Dann habe ich diese TSQL-Befehle ausgeführt:

USE master
GO
CREATE ASYMMETRIC KEY FileUtilitiesKey FROM EXECUTABLE FILE = 'J:\FileUtilities.dll' 
CREATE LOGIN CLRLogin FROM ASYMMETRIC KEY FileUtilitiesKey 
GRANT EXTERNAL ACCESS ASSEMBLY TO CLRLogin 
ALTER DATABASE database SET TRUSTWORTHY ON;

Dann habe ich die gespeicherte CLR-Proc von Visual Studio aus in meiner Zieldatenbank bereitgestellt und dieses TSQL zur Ausführung über SSMS verwendet, das mit Windows-Authentifizierung angemeldet ist:

DECLARE @i INT
--EXEC FileExists '\\\\server\\share\\folder\\file.dat', @i OUT
EXEC FileExists 'j:\\file.dat', @i OUT
SELECT @i

Egal, ob ich eine lokale Datei oder eine Netzwerkdatei versuche, ich erhalte immer eine 0.Vielleicht versuche ich es später noch einmal, aber vorerst werde ich versuchen, einen anderen Weg einzuschlagen.Wenn jemand etwas Licht ins Dunkel bringen kann, wäre ich sehr dankbar.

@Paul, dieser Code scheint zu funktionieren.Haben Sie versucht, eine Ablaufverfolgung in diese Methode einzubauen, um sicherzugehen? Convert.ToString(fileName) Verschließt es nicht irgendwie den Weg?

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top