已安装了Java的Samba驱动器,但文件资源管理器中的驱动器标签没有更新。

huangapple go评论69阅读模式
英文:

Mounted samba drive with Java but the drive label isn't updating in file explorer?

问题

我正在开发一个Java GUI应用程序,可以将Samba共享卸载和挂载到特定的盘符。当用户选择时,驱动器成功卸载和挂载,但是在Windows文件资源管理器中,驱动器标签(驱动器的显示名称)没有更新。

我使用ProcessBuilder来执行命令,当我自己使用Windows CMD时,我没有遇到这个问题,但我运行的命令是相同的。

processBuilder = new ProcessBuilder("net",
        "use",
        "T:",
        "\\\\" + SERVER_NAME + "\\" + SHARE_NAME + "\\" + FOLDER,
        "/USER:" + USERNAME,
        PASSWORD,
        "/PERSISTENT:NO"
        );

真正奇怪的是,当我第一次打开应用程序内置的文件浏览器时,它显示了带有正确标签的驱动器,尽管Windows文件资源管理器显示的是旧标签。但这只在第一次打开时才会出现,然后它将不会显示任何新的驱动器标签。

我猜这更多是一个与Windows相关的问题,而不是代码问题。有什么办法可以强制Windows刷新标签或其他想法吗?

更新 - 我发现如果我在任务管理器中重新启动explorer.exe进程,当我重新打开文件资源管理器时,它会刷新标签。我不想在我的应用程序中这样做,因为它会刷新整个Windows桌面界面,但这可能会提供一些线索。

更新2 - 我还注意到,如果我在卸载初始驱动器和挂载所选驱动器之间使用Thread.sleep()休眠5秒,标签会正确更新...这样做可以解决问题,但是我发现这是目前找到的最佳解决方案,我正在确定我需要休眠线程的最短时间... 1秒不够长。

英文:

I'm working on a Java GUI application that can unmount and mount Samba shares to a specific letter drive. The drives are successfully unmounted and mounted when the user selects, however the drive label (the display name of drive) is not updating in windows file explorer.

I'm using the ProcessBuilder to execute the command and I don't run into this issue when I just use the windows CMD myself but the command I run is identical.

processBuilder = new ProcessBuilder( "net",
        "use",
        "T:",
        "\\\\" + SERVER_NAME + "\\" + SHARE_NAME + "\\" + FOLDER,
        "/USER:" + USERNAME,
        PASSWORD,
        "/PERSISTENT:NO"
        );

The really strange thing is that when I open the file browser that's built into my applications gui for the first time, it shows the drive with the correct label, even though windows file explorer shows the old label. This is only the case when you open it for the first time though and then it will not show any new drive labels.

I'm guessing this is more of a windows specific thing that I'm dealing with and not an issue with the code. Any ideas how I can force windows to refresh the label or any other ideas?

Update - I discovered that if I restart explorer.exe process in task manager it will refresh the label when I reopen the file explorer. I don't want to do this in my application because it refreshes the entire windows desktop interface but it might provide some insight.

Update 2 - I also noticed that if I Thread.sleep() for 5 seconds between unmounting the initial drive and mounting the selected drive the label updates correctly... This does the job but it's annoying that this is the best solution I've found so far. I'm currently figuring out the minimum amount of time I need to sleep the thread for... 1 second was not long enough.

答案1

得分: 1

Windows将当前用户的标签与网络位置的映射保存在注册表中,参见这个SuperUser帖子

根据问题评论中的讨论,显然在生成的进程停止和注册表更新未完全完成之间存在某种交互作用。也就是说,进程创建了映射,触发了注册表的更新,但如果进程在注册表更新完成之前终止,注册表更新将被取消(或者甚至可能没有被调用?可能需要进程句柄仍然存在于内部操作系统触发器中才能调用)。

因此,“正确”的解决方案不是使用waitFor()(因为它不起作用),也不是使用sleep(n)(因为没有可靠的方法告诉任何n会起作用,因为受操作系统调度的影响)。“正确”的解决方案是保持进程活动,并检查注册表更新是否发生(即标签是否已注册并可用),当更新完成后,再关闭进程。

当然,从实用的角度来看,sleep(10_000);应该能解决问题,你只是浪费了一些可忽略的CPU周期和内存。

英文:

Windows keeps the mapping of label to network locations for the current user in the registry, cf. this SuperUser post.

Apparently—based on the discussion in comments on the question—there is some kind of interaction between the spawned process being stopped and the registry update not finishing fully. I.e., the process creates the mapping, which triggers an update in the registry, but if the process terminates before the registry update is finished, the registry update is cancelled (or maybe not even invoked? It may be that in order it to be invoked, the process handle, which created the mapping still has to be there for the internal OS trigger).

Thus, the "proper" solution is not a waitFor() (as it does not work), or a sleep(n) (because there is no realiable way to tell for any n that it will work, because of OS scheduling). The "proper" solution is to keep the process alive and check whether the registry update happens (i.e., the label is registered and available) and when it has been finished, then you can close the process.

Of course, pragmatically speaking, a sleep(10_000); should do the trick, you are just wasting some negligible amount of CPU cycles and RAM.

答案2

得分: 0

我有两种可能有效的方法。

  1. 模拟按下F5键事件: 在Java中模拟按下F5键事件,目标是文件资源管理器窗口。

示例代码:

import java.awt.Robot;
import java.awt.event.KeyEvent;

public class RefreshExplorer {
    public static void main(String[] args) {
        try {
            Robot robot = new Robot();
            robot.keyPress(KeyEvent.VK_F5);
            robot.keyRelease(KeyEvent.VK_F5);
        } catch (Exception e) {
            System.out.println(e);
            e.printStackTrace();
        }
    }
}
  1. 使用循环优化sleep方法: 在Java中使用循环,每500毫秒检查一次任务是否完成,这样你就不需要等待5秒,可以通过尝试更短的时间找到最快的有效时间。

在代码中,isDriveLabelUpdated()方法是你需要编写的方法,用于检查驱动器标签是否已更新,并返回一个布尔值。

示例代码:

for (int i = 0; i < 10; i++) { 
    Thread.sleep(500);  // 等待500毫秒
    if (isDriveLabelUpdated()) { 
        break;  // 如果检测到更新,则退出循环
    }
}

如果你需要第二种方法的帮助或有任何问题,请随时提问。

英文:

I have two methods that could work.

  1. Simulate F5 Key Press Event: Just simulate the F5 Key Press event in Java. It should target the File Explorer windows.

Sample Code:

import java.awt.Robot;
import java.awt.event.KeyEvent;

public class RefreshExplorer {
    public static void main(String[] args) {
        try {
            Robot robot = new Robot();
            robot.keyPress(KeyEvent.VK_F5);
            robot.keyRelease(KeyEvent.VK_F5);
        } catch (Exception e) {
            System.out.println(e);
            e.printStackTrace();
        }
    }
}
  1. Optimize the sleep method with a loop: By using a loop in Java that checks lets say every 500 ms if the job is done, you don't need to wait 5 seconds and you can find out the fastest time that works by trying shorter times.

In the code the method isDriveLabelUpdated() would be a method you need to code that checks if the drive label was updated or not and returns a boolean.

Sample Code:

for (int i = 0; i &lt; 10; i++) { 
    Thread.sleep(500);  // Sleep for 500 milliseconds
    if (isDriveLabelUpdated()) { 
        break;  // Exit the loop if the update is detected
    }
}

If you need help for the second idea or you have any questions feel free to ask.

huangapple
  • 本文由 发表于 2023年8月8日 22:54:37
  • 转载请务必保留本文链接:https://go.coder-hub.com/76860750.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定