2016-05-03 19 views
0

PythonベースのGUIアプリケーションからMS-Officeドキュメントを開始したいとします。私はサブプロセスモジュールを使ってコマンドラインを使用して、実行可能なアプリケーションをファイルにマッピングする不運な作業をWindowsにさせていますが、ファイルがネットワーク上のどこかですでに開かれている場合は自動的に失敗します。私は静かに失敗する代わりにメッセージボックスを与えることを好むだろう。ファイルの修正時間を変更せずにこのシナリオをどのように伝えることができますか?Windows上のPythonで別のアプリケーションがファイルを使用しているかどうかを確認する方法

答えて

1

ファイルの名前を現在の名前に変更することができます。別のアプリケーションがファイルを開いている場合、これはPermissionError例外で失敗します。それが失敗しなければ、それは完全な無操作です。したがって:

def start_file(file): 
    if os.path.exists(file): 
     try: os.rename(file, file) # This does NOTHING if the file is available, or fails. 
     except PermissionError: messagebox.showwarning('File in Use', 'The file appears to be already open. Sorry about that.') 
     else: subprocess.call(['start', '/B', file], shell=True) 
    else: messagebox.showwarning('Missing File', 'That files does not yet exist. Sorry about that.') 

純粋主義者は、これは少なくとも一つの競合状態の対象となるが、ビューの人間が相互作用点から、それは問題の時間の99.999%を解決しないことを指摘します。残りの部分については、Billを責めます:

+0

ファイルがすでに削除共有なしで開いている場合(つまり、名前の変更がリンク解除のように動作する場合)、「rename」は失敗します。 Cランタイムは既定で読み取りと書き込みの共有を持つファイルを開くが、共有は削除しないので、コードは共通の既定の共有モードに基づいて開いているハンドルを検出します。プログラムが削除共有を使用してファイルを開くと、動作しません。ターゲットアプリはおそらく削除アクセスを共有していないだろうが、私はそれも排他的な書き込みアクセスを望んでいると思う。後者を確認するには、WinAPI ['CreateFile'](https://msdn.microsoft.com/en-us/library/aa363858)を書き込み共有なしで呼び出す必要があります。 – eryksun

+0

'start'の'/B'オプションは、現在のプロセスがコンソールアプリケーションである場合にのみ重要なターゲットコンソールアプリケーション用の新しいコンソールの作成を防ぎます。また、プログラムがコンソールに同時にアクセスしようとすると混乱します。 '/ B'も新しいプロセスグループを作成しますが、cmdが直接' ShellExecuteEx'を使うのではなく 'CreateProcess'を呼び出すことができます。これはあなたのケースでは当てはまりません。ですから、私はあなたが 'start'なしで" file "を実行すべきだと思います。 'ShellExecuteEx'がDDEを使う間接的に' CreateProcess'を呼び出すと、cmdはプロセスハンドルを取得し、終了コードを待つことができます。 – eryksun

+0

@eryksun、ターゲットアプリケーションはMS-Officeです。これにより、開いているファイルの名前を変更できなくなります。 GUIアプリケーションで使用される '' start/b file.xlsx "shell = True"のテクニックは、良い動作のために必要であることを経験が示しているからです。私はそれをさまざまな方法でテストしました。 – Ian

関連する問題