2011-05-16 8 views
1

私は、古いC++アプリケーションと連携して動作するように設計されたプログラムを開発中です。 Age of Wondersというゲーム。 Windows VistaまたはWindows 7(UACを有効にした状態)で実行すると、ゲーム保存ファイルは実際のパスではなく仮想化パスに書き込まれます。Windows Vista/7 UACファイルシステムの仮想化に関するヘルプ

たとえば、

オリジナル: C:\プログラムファイル(x86の)\七不思議\保存

仮想化の時代: C:不思議の\ユーザー\ユーザー名\のAppData \ローカル\ VirtualStore \プログラムファイル(x86の)\年齢\ Save

私の.Netアプリケーションでは、電子メールサーバーからファイルをダウンロードし、保存フォルダに保存します。元のパスに書き込もうとすると、UACが有効なときに不正アクセス例外が発生します。 Windowsはそれを自動的に仮想化されたパスに変換しません。私はこれを回避するために、ユーザーにアプリケーションを管理者として実行させるようにしました。しかし、より洗練されたソリューションを作りたいと思います。

例外を処理してコード内の仮想化されたパスに書き込むコードを書くことができましたが、私のプログラムを何らかの形でモードに切り替えることで、Windows自体ではなく、私のコード。これは、Windowsの将来のバージョンではより長期的な解決策になると感じています。

私はインターネット上で探すのに時間を費やしていると私はこのことについて話している他の人を発見したが、誰が実際に使用できる任意のヘルプを提供していません。私が見たリンクは次のとおりです。私はそうなどの下

をプロセスを実行するために、彼らのシステム設定を変更したり、任意のアカウントを作成したユーザーを含まない溶液に必要

Should I use a VirtualStore solution on Vista?

Create Process with FS Virtualization Enabled

http://us.generation-nt.com/answer/using-settokeninformation-control-file-system-virtualization-vista-help-37057472.html

下に、私はシンプルなWindowsフォームアプリケーションのコードがあります。 1つのボタンと1つのチェックボックスがあり、このチェックボックスは仮想化モードを切り替えるためのもので、小さなテキストファイルをProgram Filesフォルダに書き込みます。私はこれを使って仮想化の動作をテストしたいと考えています。チェックボックスをオンにしたとき、誰もが私は非常に感謝される空白の機能を埋めることができますので、もし私がなど

FILE.TXTは、仮想化のパスに書き込むことが期待されます。前もって感謝します。

using System; 
using System.Collections.Generic; 
using System.Data; 
using System.Drawing; 
using System.Linq; 
using System.Text; 
using System.Windows.Forms; 
using System.IO; 
public partial class Form1 : Form 
{ 

    public Form1() 
    { 
     InitializeComponent(); 
    } 

    private void button1_Click(object sender, EventArgs e) 
    { 
     try 
     { 
      string testText = "Dave was here"; 
      File.WriteAllText("C:\\Program Files\\DaveTest\\File.txt", testText); 
     } 
     catch (Exception ex) 
     { 
      MessageBox.Show(ex.ToString()); 
     } 
    } 

    private void checkBox1_CheckedChanged(object sender, EventArgs e) 
    { 
     SetVirtualization(checkBox1.Checked); 
    } 

    private void SetVirtualization(bool enabled) 
    { 
     //What code do I need here, please provide examples than can be used 
    } 
} 

答えて

1

.NETアプリケーションが64ビットアプリケーションとして動作しているようです。このようなアプリケーションでは、仮想化(ファイル/レジストリ)が無効になっています。

あなたのアプリをx86としてコンパイルできますか?もしそうなら、そのトリックを行う必要があります。

+0

私のユーザーの何人かはx86になっているので、私はすでにx86にコンパイルしています。 –

+0

実際、私のコンパイラセットはAny CPUに設定されています。 –

+0

x64マシンでは仮想化が無効になります – Vagaus

2

あなたは仮想化をしたい場合は、マニフェストなし32ビットプロセスを必要としています。すでに32ビットのプロセスがあるように見えるので、マニフェストを取り除く必要があります。

私はあなたが現代的なテーマにした外観を放棄することと思いますので、これはあなたの素敵な光沢のあるのWinFormsアプリの不便さを期待。簡単な回避策は、仮想化を必要とするアプリのほんの一部を処理するための別のプロセスでこれをコーディングするだろう。これの利点は、残りのプロセスを仮想化する必要がないことです。

0

参考までに、私はこれを考え出しました。

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Diagnostics; 
using System.Runtime.InteropServices; 

namespace VirtualizationTest 
{ 
    public class FileVirtualizationHelper 
    { 
     #region Win32 API routines 

     enum TOKEN_INFORMATION_CLASS 
     { 
      TokenUser = 1, 
      TokenGroups, 
      TokenPrivileges, 
      TokenOwner, 
      TokenPrimaryGroup, 
      TokenDefaultDacl, 
      TokenSource, 
      TokenType, 
      TokenImpersonationLevel, 
      TokenStatistics, 
      TokenRestrictedSids, 
      TokenSessionId, 
      TokenGroupsAndPrivileges, 
      TokenSessionReference, 
      TokenSandBoxInert, 
      TokenAuditPolicy, 
      TokenOrigin, 
      MaxTokenInfoClass // MaxTokenInfoClass should always be the last enum 
     } 

     const UInt32 MAXIMUM_ALLOWED = 0x2000000; 

     [DllImport("kernel32.dll", SetLastError = true)] 
     static extern Boolean CloseHandle(IntPtr hSnapshot); 

     [DllImport("advapi32", SetLastError = true), System.Security.SuppressUnmanagedCodeSecurityAttribute] 
     static extern Boolean OpenProcessToken(IntPtr ProcessHandle, // handle to process 
              UInt32 DesiredAccess, // desired access to process 
              ref IntPtr TokenHandle); // handle to open access token 

     [DllImport("advapi32.dll", SetLastError = true)] 
     static extern Boolean SetTokenInformation(IntPtr TokenHandle, TOKEN_INFORMATION_CLASS TokenInformationClass, ref UInt32 TokenInformation, UInt32 TokenInformationLength); 

     #endregion 

     #region Public Methods 

     public static bool Enable() 
     { 
      return SetVirtualization(true); 
     } 

     public static bool Disable() 
     { 
      return SetVirtualization(false); 
     } 

     #endregion 

     #region Private Methods 

     private static bool SetVirtualization(bool DoEnable) 
     { 
      IntPtr Token = (IntPtr)0; 
      UInt32 EnableValue = DoEnable ? (UInt32)1 : (UInt32)0; 
      UInt32 EnableValueSize = sizeof(UInt32); 

      if (!OpenProcessToken(Process.GetCurrentProcess().Handle, MAXIMUM_ALLOWED, ref Token)) 
      { 
       return false; 
      } 
      if (!SetTokenInformation(Token, (TOKEN_INFORMATION_CLASS)24, ref EnableValue, EnableValueSize)) 
      { 
       CloseHandle(Token); 
       return false; 
      } 
      CloseHandle(Token); 
      return true; 
     } 

     #endregion 
    } 
} 
関連する問題