如何强制Windows重新连接到网络驱动器

12

我们试图访问一个位于网络目录中的目录,但是得到了错误的结果(C# / Windows):

var exists = Directory.Exists("Z:\\Sessions\\Data1");

"Z"是网络目录,"Sessions"是一个录制软件不断创建目录(例如"Data1")并向其中放置一些数据的目录。 似乎Windows缓存了关于Data1错误的状态:该方法返回false。但是当我通过资源管理器访问目录时,它在这里。当我使用资源管理器访问目录后再运行该方法(Directory.Exists),它返回true。当然,我可以保证在第一次尝试时目录确实存在。

这种行为的原因是什么?我能做些什么来解决它吗?

编辑: 似乎Windows无法将网络驱动器连接到远程计算机。当我尝试通过资源管理器浏览目录时,它会自动尝试连接驱动器。

所以问题变成了: 有没有办法通过.NET强制Windows尝试重新连接?

解决方案: 重新连接已断开的网络驱动器


如果您从命令提示符使用“DIR”命令访问目录,是否可以获得正确的信息?也就是说:“dir Z:\Sessions\Data1”。 - Jim Mischel
不,通过命令提示符访问目录并不会刷新网络驱动器连接。请参见我的编辑... - nepa
3个回答

7

我不确定上面的解决方案链接适用于哪个版本的 mpr.dll,但我正在使用 Win7,并且有一个略微不同的版本(尽管相似)。这个入口点是:

    [DllImport("mpr.dll", SetLastError = true, EntryPoint = "WNetRestoreSingleConnectionW", CharSet = CharSet.Unicode)]
    internal static extern int WNetRestoreSingleConnection( IntPtr windowHandle,
                                                            [MarshalAs(UnmanagedType.LPWStr)] string localDrive,
                                                            [MarshalAs(UnmanagedType.Bool)] bool useUI);

那么:

IntPtr hWnd = new IntPtr(0);
int res = WNetRestoreSingleConnection(hWnd, <your drive path>, false);

您需要添加自己的错误检查/处理。


1
尽管API未记录(仍然?!),但似乎在Windows 10上可以工作。 - user3797758

2

我也使用远程驱动器,连接需要几秒钟的时间,所以我只是耐心等待,每次都能成功。如果无法连接,它会发送电子邮件通知我,我会进行检查。

        logger.Info("Create Z: drive ");
        System.Diagnostics.Process process = new System.Diagnostics.Process();
        System.Diagnostics.ProcessStartInfo startInfo = new System.Diagnostics.ProcessStartInfo();
        startInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
        startInfo.FileName = "cmd.exe";
        startInfo.Arguments = @"/C net use z: \\" + Tools.servername + @"\SHARE_NAME_HERE /user:USER_NAME_HERE PASSWORD_HERE";
        process.StartInfo = startInfo;
        process.Start();
        logger.Info("Z: drive created ");

        // wait get Z:
        int xtimestimeout = 5;
        while (!Directory.Exists(@"Z:\") & (xtimestimeout > 0))
        {
            Application.DoEvents();
            SetBalloonTip(@"Program", @"connecting... please wait");
            ShowBalloon();
            logger.Info("Creating Z:... waiting...");
            Application.DoEvents();
            System.Threading.Thread.Sleep(3000);
            xtimestimeout -= 1;
        }

        // check for sucessfull creation of Z: in server Z:\somedirectory
        if (!Directory.Exists(@"Z:\"))
        {
            SendEmail2("Oh my... help!", "drive Z: not created <<< CHECK!");
            logger.Info("Z: email sent because of not created");
        }
        logger.Info("Z: drive created successfully.");

好的,有人用-1标记了我的答案。我不明白为什么,因为我也遇到了与问题相同的情况,而这段代码解决了它。这段代码有效,并且只使用了 .net 代码,而不是被标记为解决方案的答案所使用的外部库。 - Roger Deep
不用担心,我已经反对了它。这实际上是一个很好的解决方案,正是我想要做的。但是,我也不希望出现cmd窗口。然而,我还没有测试过你的代码,但它看起来很有前途。谢谢。 - xmen

0
这种行为的原因是什么?
引用自文档
如果您对目录没有至少只读权限,则Exists方法将返回false。

我该怎么办?

确保你正在运行的.NET应用程序是在至少具有只读权限以访问此文件夹的帐户下运行。请注意,如果您正在编写ASP.NET应用程序,则可能不是这种情况,因此根据您配置Web服务器以执行应用程序的帐户,采取必要的步骤授予权限给该帐户。


正如楼主所提到的,“当我在使用资源管理器访问目录后运行该方法(Directory.Exists)时,它返回true。” 这意味着很可能是缓存问题而不是权限问题。 - Eugene Mayevski 'Callback
1
@EugeneMayevski'EldoSCorp,当您使用资源管理器时,您是在自己的帐户下运行它。但是,当您运行ASP.NET应用程序时,它可能会在完全不同的帐户下运行。因此,我猜测OP执行验证目录存在的测试时,并不是在相同的条件下进行的:在第一种情况下,他使用了自己的帐户,而在第二种情况下,则使用了其他帐户(在这个阶段,我们只能猜测使用了哪个帐户,因为OP没有提供有关其应用程序的任何上下文信息)。 - Darin Dimitrov
问题因为我发现了一些事情而改变了,请查看我的编辑。 - nepa

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接