Windows 操作 (C++/CLI)

使用 Windows SDK 演示各种特定于 Windows 的任务。

以下主题演示了使用 Visual C++ 通过 Windows SDK 执行的各种 Windows 操作。

确定关闭是否已启动

以下代码示例演示如何确定应用程序或 .NET Framework 当前是否正在终止。 这对于访问 .NET Framework 中的静态元素很有用,因为在关闭期间,这些构造由系统完成,无法可靠使用。 首先检查 HasShutdownStarted 属性,可以通过不访问这些元素来避免潜在的失败。

示例

// check_shutdown.cpp
// compile with: /clr
using namespace System;
int main()
{
   if (Environment::HasShutdownStarted)
      Console::WriteLine("Shutting down.");
   else
      Console::WriteLine("Not shutting down.");
   return 0;
}

确定用户交互状态

以下代码示例演示如何确定代码是否在用户交互上下文中运行。 如果 UserInteractive 为 false,则代码作为服务进程或从 Web 应用程序内部运行,在这种情况下,不应尝试与用户交互。

示例

// user_interactive.cpp
// compile with: /clr
using namespace System;

int main()
{
   if ( Environment::UserInteractive )
      Console::WriteLine("User interactive");
   else
      Console::WriteLine("Noninteractive");
   return 0;
}

从 Windows 注册表中读取数据

下面的代码示例使用 CurrentUser 键从 Windows 注册表读取数据。 首先,使用 GetSubKeyNames 方法枚举子键,然后使用 OpenSubKey 方法打开 Identities 子键。 与根键一样,每个子键都由 RegistryKey 类表示。 最后一点,新的 RegistryKey 对象用于枚举键/值对。

示例

// registry_read.cpp
// compile with: /clr
using namespace System;
using namespace Microsoft::Win32;

int main( )
{
   array<String^>^ key = Registry::CurrentUser->GetSubKeyNames( );

   Console::WriteLine("Subkeys within CurrentUser root key:");
   for (int i=0; i<key->Length; i++)
   {
      Console::WriteLine("   {0}", key[i]);
   }

   Console::WriteLine("Opening subkey 'Identities'...");
   RegistryKey^ rk = nullptr;
   rk = Registry::CurrentUser->OpenSubKey("Identities");
   if (rk==nullptr)
   {
      Console::WriteLine("Registry key not found - aborting");
      return -1;
   }

   Console::WriteLine("Key/value pairs within 'Identities' key:");
   array<String^>^ name = rk->GetValueNames( );
   for (int i=0; i<name->Length; i++)
   {
      String^ value = rk->GetValue(name[i])->ToString();
      Console::WriteLine("   {0} = {1}", name[i], value);
   }

   return 0;
}

备注

Registry 类只是 RegistryKey 的静态实例的容器。 每个实例表示根注册表节点。 实例为 ClassesRootCurrentConfigCurrentUserLocalMachineUsers

除了是静态的,Registry 类中的对象也是只读的。 此外,创建用于访问注册表对象内容的 RegistryKey 类的实例也是只读的。 有关如何替代此行为的示例,请参阅如何:将数据写入 Windows 注册表 (C++/CLI)

Registry 类中有两个附加对象:DynDataPerformanceData。 这两个对象都是 RegistryKey 类的实例。 DynData 对象包含动态注册表信息,该信息仅在 Windows 98 和 Windows ME 中受支持。 PerformanceData 对象可用于访问使用 Windows 性能监视系统的应用程序的性能计数器信息。 PerformanceData 节点表示实际上并未存储在注册表中的信息,因此无法使用 Regedit.exe 进行查看。

读取 Windows 性能计数器

某些应用程序和 Windows 子系统通过 Windows 性能系统公开性能数据。 可以使用驻留在 System.Diagnostics 命名空间中的 PerformanceCounterCategoryPerformanceCounter 类访问这些计数器。

以下代码示例使用这些类来检索和显示由 Windows 更新的计数器,指示处理器忙碌的时间百分比。

注意

此示例需要在 Windows Vista 上运行的管理员特权。

示例

// processor_timer.cpp
// compile with: /clr
#using <system.dll>

using namespace System;
using namespace System::Threading;
using namespace System::Diagnostics;
using namespace System::Timers;

ref struct TimerObject
{
public:
   static String^ m_instanceName;
   static PerformanceCounter^ m_theCounter;

public:
   static void OnTimer(Object^ source, ElapsedEventArgs^ e)
   {
      try
      {
         Console::WriteLine("CPU time used: {0,6} ",
          m_theCounter->NextValue( ).ToString("f"));
      }
      catch(Exception^ e)
      {
         if (dynamic_cast<InvalidOperationException^>(e))
         {
            Console::WriteLine("Instance '{0}' does not exist",
                  m_instanceName);
            return;
         }
         else
         {
            Console::WriteLine("Unknown exception... ('q' to quit)");
            return;
         }
      }
   }
};

int main()
{
   String^ objectName = "Processor";
   String^ counterName = "% Processor Time";
   String^ instanceName = "_Total";

   try
   {
      if ( !PerformanceCounterCategory::Exists(objectName) )
      {
         Console::WriteLine("Object {0} does not exist", objectName);
         return -1;
      }
   }
   catch (UnauthorizedAccessException ^ex)
   {
      Console::WriteLine("You are not authorized to access this information.");
      Console::Write("If you are using Windows Vista, run the application with ");
      Console::WriteLine("administrative privileges.");
      Console::WriteLine(ex->Message);
      return -1;
   }

   if ( !PerformanceCounterCategory::CounterExists(
          counterName, objectName) )
   {
      Console::WriteLine("Counter {0} does not exist", counterName);
      return -1;
   }

   TimerObject::m_instanceName = instanceName;
   TimerObject::m_theCounter = gcnew PerformanceCounter(
          objectName, counterName, instanceName);

   System::Timers::Timer^ aTimer = gcnew System::Timers::Timer();
   aTimer->Elapsed += gcnew ElapsedEventHandler(&TimerObject::OnTimer);
   aTimer->Interval = 1000;
   aTimer->Enabled = true;
   aTimer->AutoReset = true;

   Console::WriteLine("reporting CPU usage for the next 10 seconds");
   Thread::Sleep(10000);
   return 0;
}

从剪贴板中检索文本

下面的代码示例使用 GetDataObject 成员函数返回指向 IDataObject 接口的指针。 然后,可在此接口中查询数据格式,并用它来检索实际数据。

示例

// read_clipboard.cpp
// compile with: /clr
#using <system.dll>
#using <system.Drawing.dll>
#using <system.windows.forms.dll>

using namespace System;
using namespace System::Windows::Forms;

[STAThread] int main( )
{
   IDataObject^ data = Clipboard::GetDataObject( );

   if (data)
   {
      if (data->GetDataPresent(DataFormats::Text))
      {
         String^ text = static_cast<String^>
           (data->GetData(DataFormats::Text));
         Console::WriteLine(text);
      }
      else
         Console::WriteLine("Nontext data is in the Clipboard.");
   }
   else
   {
      Console::WriteLine("No data was found in the Clipboard.");
   }

   return 0;
}

检索当前用户名

下面的代码示例演示了检索当前用户名(登录到 Windows 的用户名)的情况。 名称存储在 UserName 字符串中,该字符串在 Environment 命名空间中定义。

示例

// username.cpp
// compile with: /clr
using namespace System;

int main()
{
   Console::WriteLine("\nCurrent user: {0}", Environment::UserName);
   return 0;
}

检索 .NET Framework 的版本

以下代码示例演示如何使用 Version 属性确定当前安装的 .NET Framework 的版本,该属性是指向包含版本信息的 Version 对象的指针。

示例

// dotnet_ver.cpp
// compile with: /clr
using namespace System;
int main()
{
   Version^ version = Environment::Version;
   if (version)
   {
      int build = version->Build;
      int major = version->Major;
      int minor = version->Minor;
      int revision = Environment::Version->Revision;
      Console::Write(".NET Framework version: ");
      Console::WriteLine("{0}.{1}.{2}.{3}",
            build, major, minor, revision);
   }
   return 0;
}

检索本地计算机名称

以下代码示例演示检索本地计算机名称(显示在网络上的计算机名称)的情况。 可以通过获取在 Environment 命名空间中定义的 MachineName 字符串来完成此操作。

示例

// machine_name.cpp
// compile with: /clr
using namespace System;

int main()
{
   Console::WriteLine("\nMachineName: {0}", Environment::MachineName);
   return 0;
}

检索 Windows 版本

以下代码示例演示如何检索当前操作系统的平台和版本信息。 此信息存储在 System.Environment.OSVersion 属性中,由概括地描述 Windows 版本的枚举和包含操作系统的确切版本的 Version 对象组成。

示例

// os_ver.cpp
// compile with: /clr
using namespace System;

int main()
{
   OperatingSystem^ osv = Environment::OSVersion;
   PlatformID id = osv->Platform;
   Console::Write("Operating system: ");

   if (id == PlatformID::Win32NT)
      Console::WriteLine("Win32NT");
   else if (id == PlatformID::Win32S)
      Console::WriteLine("Win32S");
   else if (id == PlatformID::Win32Windows)
      Console::WriteLine("Win32Windows");
   else
      Console::WriteLine("WinCE");

   Version^ version = osv->Version;
   if (version)
   {
      int build = version->Build;
      int major = version->Major;
      int minor = version->Minor;
      int revision = Environment::Version->Revision;
      Console::Write("OS Version: ");
      Console::WriteLine("{0}.{1}.{2}.{3}",
                   build, major, minor, revision);
   }

   return 0;
}

检索自启动以来经过的时间

以下代码示例演示如何确定滴答计数或自 Windows 启动以来经过的毫秒数。 此值存储在 System.Environment.TickCount 成员中,因为它是一个 32 位值,大约每 24.9 天重置为零。

示例

// startup_time.cpp
// compile with: /clr
using namespace System;

int main( )
{
   Int32 tc = Environment::TickCount;
   Int32 seconds = tc / 1000;
   Int32 minutes = seconds / 60;
   float hours = static_cast<float>(minutes) / 60;
   float days = hours / 24;

   Console::WriteLine("Milliseconds since startup: {0}", tc);
   Console::WriteLine("Seconds since startup: {0}", seconds);
   Console::WriteLine("Minutes since startup: {0}", minutes);
   Console::WriteLine("Hours since startup: {0}", hours);
   Console::WriteLine("Days since startup: {0}", days);

   return 0;
}

将文本存储在剪贴板中

以下代码示例使用 System.Windows.Forms 命名空间中定义的 Clipboard 对象来存储字符串。 此对象提供两个成员函数:SetDataObjectGetDataObject。 通过将派生自 Object 的任何对象发送到 SetDataObject,将数据存储在剪贴板中。

示例

// store_clipboard.cpp
// compile with: /clr
#using <System.dll>
#using <System.Drawing.dll>
#using <System.Windows.Forms.dll>

using namespace System;
using namespace System::Windows::Forms;

[STAThread] int main()
{
   String^ str = "This text is copied into the Clipboard.";

   // Use 'true' as the second argument if
   // the data is to remain in the clipboard
   // after the program terminates.
   Clipboard::SetDataObject(str, true);

   Console::WriteLine("Added text to the Clipboard.");

   return 0;
}

将数据写入 Windows 注册表

以下代码示例使用 CurrentUser 键创建与 Software 键对应的 RegistryKey 类的可写实例。 然后使用 CreateSubKey 方法创建新键并将其添加到键/值对。

示例

// registry_write.cpp
// compile with: /clr
using namespace System;
using namespace Microsoft::Win32;

int main()
{
   // The second OpenSubKey argument indicates that
   // the subkey should be writable.
   RegistryKey^ rk;
   rk  = Registry::CurrentUser->OpenSubKey("Software", true);
   if (!rk)
   {
      Console::WriteLine("Failed to open CurrentUser/Software key");
      return -1;
   }

   RegistryKey^ nk = rk->CreateSubKey("NewRegKey");
   if (!nk)
   {
      Console::WriteLine("Failed to create 'NewRegKey'");
      return -1;
   }

   String^ newValue = "NewValue";
   try
   {
      nk->SetValue("NewKey", newValue);
      nk->SetValue("NewKey2", 44);
   }
   catch (Exception^)
   {
      Console::WriteLine("Failed to set new values in 'NewRegKey'");
      return -1;
   }

   Console::WriteLine("New key created.");
   Console::Write("Use REGEDIT.EXE to verify ");
   Console::WriteLine("'CURRENTUSER/Software/NewRegKey'\n");
   return 0;
}

备注

可以使用 .NET Framework 通过 RegistryRegistryKey 类访问注册表,这两个类都在 Microsoft.Win32 命名空间中定义。 Registry 类是 RegistryKey 类的静态实例的容器。 每个实例表示根注册表节点。 实例为 ClassesRootCurrentConfigCurrentUserLocalMachineUsers

Environment

另请参阅

使用 C++/CLI (Visual C++) 进行 .NET 编程