2

pywin32 バインディングを使用していくつかの Excel スプレッドシートを編集するプログラムのインストーラーを作成しようとしています。py2exe を使用して実行可能ファイルを作成しましたが、デスクトップ上のフォルダーから実行可能ファイルを実行するとすべてが機能します。ただし、プログラムを C:\Program Files\ または任意のシステムの同等のフォルダーにインストールする単一のインストーラー ファイルを配布できるようにしたいと考えています。私もこれに成功しましたが、pywin32 バインディングを使用すると、作業ディレクトリがどこにあっても一時ファイルが作成されます。

新しいバージョンの Windows では、管理者のみがこれらのディレクトリへの書き込み権限を持つようになっているため、これは非常に問題があります。このため、これらのディレクトリからアプリを実行すると、次のエラーで失敗します。

WindowsError: [Error 5] Access is denied: 'C:\\Program Files (x86)\\DataPlotter\\.\\win32com\\gen_py\
\00020813-0000-0000-C000-000000000046x0x1x6'

管理者権限で実行するようにアプリを変更することは、脆弱性をもたらす可能性があるため、悪い解決策です。

この問題の修正や、pywin32 バインディングが一時ファイルの場所として使用する場所を変更する方法を知っている人はいますか?

4

2 に答える 2

1

contextlib.contextmanager未処理の例外が発生した場合でも以前の現在のディレクトリを復元したい場合、デコレータを使用してコードをコンテキスト マネージャに変換する方法についての回答へのコメントで説明した方法は、少し単純化されすぎていました。これを実現するには、try...finally句を前後に追加する必要もありますyield(以下を参照)。

また、いくつかのクラスのメソッドではなく、スタンドアロンの関数にして、引数として切り替え先のディレクトリを渡す方が良いと思います。どちらも、より汎用的で再利用しやすいものにします。同じ名前の Windows および Unix シェル コマンドと類似pushd()しているため、私はそれを呼び出しました。

from contextlib import contextmanager
import os
import tempfile

@contextmanager
def pushd(dir=None):
    """ Context manager which saves the current working directory before
        changing either to the one passed or the default folder for temporary
        files and then restores the former after the controlled suite of
        statements have executed. This will happened even if an unhandled
        exception occurs within the block. """
    cwd = os.getcwd()
    os.chdir(dir if dir is not None else tempfile.gettempdir())
    try:
        yield
    finally:
        os.chdir(cwd)

# sample usage

with pushd():
    self.xl = win32com.client.gencache.EnsureDispatch("Excel.Application")

オプションの変数がブロック内で参照できるように、以前の現在の作業ディレクトリを示す値を受け取ることyield cwdができるように、何もしないのではなくa を実行することも役立つ場合があります。as

于 2012-08-21T17:19:40.730 に答える
0

これはばかげたハックソリューションですが、この問題は pywin32 で回避策を実行することで回避できます。

現在の作業ディレクトリを一時ディレクトリなど、書き込みが安全であることが保証されているディレクトリに切り替えることで、問題を回避できます。

#Save the current working directory and then switch back once
#excel has been started. This is so pywin32 does not ruin everything
#by trying to write in the current directory without the proper 
#permission. This mainly happens (for me) when the program is installed in 
#program files which requires administrator permissions to write to.

import os
import tempfile
import win32com.client

cwd = os.getcwd()
tdir =  tempfile.gettempdir()
os.chdir(tdir)
self.xl = win32com.client.gencache.EnsureDispatch("Excel.Application") 
os.chdir(cwd)

注意: 最後に元の作業ディレクトリに戻るスイッチは必要ありませんが、必要に応じて機能します (私が行ったように)。

martineau は、contextmanager を使用して、以下でこれを行うためのより堅牢な方法を提案しました。

from contextlib import contextmanager

@contextmanager
def tempManager(self):
    cwd = os.getcwd()
    tdir =  tempfile.gettempdir()
    os.chdir(tdir)
    yield
    os.chdir(cwd)

with self.tempManager():
    self.xl = win32com.client.gencache.EnsureDispatch("Excel.Application")
于 2012-08-20T21:12:38.183 に答える