Ich habe eine Klasse, die für WNetUseConnection
GC.KeepAlive zu bewahren einen Kontext
Hier eine Implementierung (nur als Referenz) ist eine einfache Hülle ist:
internal class RemoteFileSystemContext : IDisposable
{
private readonly string _remoteUnc;
private bool _isConnected;
public RemoteFileSystemContext(string remoteUnc, string username, string password, bool promptUser)
{
if (WindowsNetworking.TryConnectToRemote(remoteUnc, username, password, promptUser))
{
_isConnected = true;
_remoteUnc = remoteUnc;
}
else
{
GC.SuppressFinalize(this);
}
}
public void Dispose()
{
Dispose(true);
}
~RemoteFileSystemContext()
{
Dispose(false);
}
private void Dispose(bool isDisposing)
{
if (!_isConnected)
return;
_isConnected = false;
if (isDisposing)
{
GC.SuppressFinalize(this);
}
WindowsNetworking.DisconnectRemote(_remoteUnc);
}
}
und hier ist Nutzung:
using (var context = WindowsNetworking.CreateRemoteContext(storagePath, login, pass))
{
// do something with storagePath
GC.KeepAlive(context);
}
Die Frage ist, ob ich GC.KeepAlive(context)
schreiben soll oder nicht? Ich meine, ich habe keinen solchen Code geschrieben, bis ich einen Artikel gelesen habe (etwa AsyncLock
, aber jetzt kann ich keinen Link finden), und jetzt bin ich mir nicht sicher, ob GC einen Finalizer aufrufen kann, bevor diese Methode beendet ist. Theoretisch sollte es Dispose
in finally
Abschnitt von using
verwenden, aber dieser Artikel wurde von einem intelligenten Kerl geschrieben, also bin ich jetzt nicht sicher.
Nur für den Fall, bietet ich Code für referenzierte Klasse:
public static class WindowsNetworking
{
public static bool TryConnectToRemote(string remoteUnc, string username, string password, bool promptUser = false)
{
bool isUnc = remoteUnc != null && remoteUnc.Length >= 2 && remoteUnc[0] == '\\' && remoteUnc[1] == '\\';
if (!isUnc)
{
return false;
}
ConnectToRemote(remoteUnc, username, password, promptUser);
return true;
}
public static IDisposable CreateRemoteContext(string remoteUnc, string username, string password, bool promptUser = false)
{
return new RemoteFileSystemContext(remoteUnc, username, password, promptUser);
}
public static void DisconnectRemote(string remoteUNC)
{
var ret = (NetworkError) WNetCancelConnection2(remoteUNC, CONNECT_UPDATE_PROFILE, false);
if (ret != NetworkError.NO_ERROR)
{
throw new Win32Exception((int) ret, ret.ToString());
}
}
[DllImport("Mpr.dll")]
private static extern int WNetUseConnection(
IntPtr hwndOwner,
NETRESOURCE lpNetResource,
string lpPassword,
string lpUserID,
int dwFlags,
string lpAccessName,
string lpBufferSize,
string lpResult
);
[DllImport("Mpr.dll")]
private static extern int WNetCancelConnection2(
string lpName,
int dwFlags,
bool fForce
);
[StructLayout(LayoutKind.Sequential)]
private class NETRESOURCE
{
public int dwScope = 0;
public int dwType = 0;
public int dwDisplayType = 0;
public int dwUsage = 0;
public string lpLocalName = "";
public string lpRemoteName = "";
public string lpComment = "";
public string lpProvider = "";
}
private static void ConnectToRemote(string remoteUNC, string username, string password, bool promptUser)
{
NETRESOURCE nr = new NETRESOURCE
{
dwType = RESOURCETYPE_DISK,
lpRemoteName = remoteUNC
};
NetworkError ret;
if (promptUser)
ret = (NetworkError) WNetUseConnection(IntPtr.Zero, nr, "", "", CONNECT_INTERACTIVE | CONNECT_PROMPT, null, null, null);
else
ret = (NetworkError) WNetUseConnection(IntPtr.Zero, nr, password, username, 0, null, null, null);
if (ret != NetworkError.NO_ERROR)
{
throw new Win32Exception((int) ret, ret.ToString());
}
}
}
Ich würde nein sagen. Ohne den Artikel ist es schwierig zu sagen, welchen Punkt dieser "schlaue Typ" eigentlich gemacht hat und ob Sie ihn richtig interpretiert haben. –
Es ist nur eine Geschichte für "von wo es kommt". Frage nicht über irgendjemanden, sondern über Finalisierung. –
Ich kann sagen, "Sie brauchen hier kein' GC.KeepAlive' ". Ich könnte es sogar als Antwort posten, ich bin selbst ein vernünftiger Klugscheißer (und auch bescheiden!), Und vielleicht bin ich sogar überzeugend.Das Problem ist, ich weiß nicht, welchen Punkt ich gegen * argumentiere, weil Sie nicht zu diesem Artikel verlinken oder sagen können, warum Sie glauben, dass es * in diesem Kontext * gelten kann. –