为两个 TargetPlatformVersion 编译一个 Visual Studio C# 项目
Compile a Visual Studio C# project for two TargetPlatformVersion
我开发了一个 .NET windows 应用程序,它可以在 Windows 7 和 8.1 上运行。然后我添加了Windows8自带的Toast通知功能(出自这个问题:How can I use the Windows.UI namespace from a regular (Non-Store) Win32 .NET application?)。
这也有效,我只需要添加:
<PropertyGroup>
<TargetPlatformVersion>8.0</TargetPlatformVersion>
</PropertyGroup>
到项目文件。
由于我从 Windows 8.1 SDK C:\Program Files (x86)\Windows Kits.1\References\CommonConfiguration\Neutral\Windows.winmd
引用了 Windows.winmd 文件,可执行文件不再在 Windows 7 上启动!我双击就是这样。没有错误,没有消息。
由于我没有在网上找到任何解决方案,这就是我的问题所在:我如何做到这两点:向我的用户提供 toast 功能并制作相同的功能.exe 运行 在 Windows 7?
提前致谢!
编辑
事实证明,虽然 TargetPlatformVersion 设置为 8.0,但可执行文件无论如何都会在 Windows 7 上启动,但一旦程序尝试加载 Windows 8 库,就会崩溃:
An unhandled exception of type 'System.TypeLoadException' occurred in ToastTester.exe.
Additional information: Could not find Windows Runtime type 'Windows.UI.Notifications.ToastNotificationManager'.
在线Application.Run(new Form1());
在第 9 行的 Form1.cs 中,我有 using Windows.UI.Notifications;
在 运行 时间内避免此异常的最佳方法是什么,即使预计此可执行文件将 运行 在 Windows 7 等环境中 Windows.UI.Notifications =]命名空间肯定不可用?
我设计了自己的解决方法,以便能够支持 Windows 8 个 toast,同时防止在 运行 on Windows 7 时由于缺少库而导致应用程序崩溃。注意:我正在使用 Singleton 设计模式(成员 INSTANCE
),但您可以随时使用其他方式。
ShellLink.cs is taken from here
Win8Toaster.cs:
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Windows.Data.Xml.Dom;
using Windows.UI.Notifications;
namespace ToastManager
{
class Win8Toaster
{
public const string APPUSERMODELID = "YourCompany.YourApplicationName";
public static string ShortcutLocation;
public static ToastNotifier ToastNotifier;
private static Win8Toaster _INSTANCE = null;
public static Win8Toaster INSTANCE
{
get
{
if (_INSTANCE == null)
{
_INSTANCE = new Win8Toaster();
}
return _INSTANCE;
}
}
public Win8Toaster()
{
ShortcutLocation = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + @"\Microsoft\Windows\Start Menu\Programs\YourCompany\YourApplication.lnk");
//We need a start menu shortcut (a ShellLink object) to show toasts.
if (!File.Exists(ShortcutLocation))
{
string directory = Path.GetDirectoryName(ShortcutLocation);
if (!Directory.Exists(directory))
{
Directory.CreateDirectory(directory);
}
using (ShellLink shortcut = new ShellLink())
{
shortcut.TargetPath = System.Reflection.Assembly.GetEntryAssembly().Location;
shortcut.Arguments = "";
shortcut.AppUserModelID = APPUSERMODELID;
shortcut.Save(ShortcutLocation);
}
}
ToastNotifier = ToastNotificationManager.CreateToastNotifier(APPUSERMODELID);
}
public void ShowToast(ToastContent Content)
{
XmlDocument ToastContent = new XmlDocument();
ToastContent.LoadXml("<toast><visual><binding template=\"ToastImageAndText02\"><image id=\"1\" src=\"file:///" + Content.ImagePath + "\"/><text id=\"1\">" + Content.Text1 + "</text><text id=\"2\">" + Content.Text2 + "</text></binding></visual></toast>");
ToastNotification thisToast = new ToastNotification(ToastContent);
ToastNotifier.Show(thisToast);
}
}
}
Toaster.cs
using System;
using System.Collections.Generic;
using System.Windows.Forms;
namespace ToastManager
{
public static class Toaster
{
private static Win8Toaster ActiveToaster;
public static bool Win8ToasterAvailable = true;
public static void ShowToast(ToastContent Content)
{
if (Win8ToasterAvailable)
{
if (ActiveToaster == null)
{
if (Environment.OSVersion.Version.Major > 6 || Environment.OSVersion.Version.Major == 6 && Environment.OSVersion.Version.Minor >= 2)
{
try
{
ActiveToaster = Win8Toaster.INSTANCE;
}
catch (Exception ex)
{
Win8ToasterAvailable = false;
}
}
else
{
Win8ToasterAvailable = false;
}
}
ActiveToaster.ShowToast(Content);
}
else
{
//Use alternative notifications because Windows 8 Toasts are not available
}
}
}
//I also wrote my own toast content structure:
public class ToastContent
{
public string ImagePath, Text1, Text2;
public ToastContent(string ImagePath, string Text1, string Text2)
{
this.ImagePath = ImagePath;
this.Text1 = Text1;
this.Text2 = Text2;
}
}
}
现在您已经掌握了必要的 类,下面是如何使用它(非常简单,是吧?):
ToastManager.Toaster.ShowToast(new ToastManager.ToastContent(@"..\path\toyour\image.png", "Your Application Name", "Time: " + DateTime.Now.ToLongTimeString()));
此示例显示带有当前系统时间的 toast 通知,如果您使用的是 Windows 7.
,则不显示任何内容
设计建议:
我使用 WinForms 设计了一个通知 window,它看起来与 Windows 8 中的通知类似,并模拟相同的功能,只是使用我自己的表单。或者,您也可以实现托盘图标并显示一些通知气泡。
我开发了一个 .NET windows 应用程序,它可以在 Windows 7 和 8.1 上运行。然后我添加了Windows8自带的Toast通知功能(出自这个问题:How can I use the Windows.UI namespace from a regular (Non-Store) Win32 .NET application?)。 这也有效,我只需要添加:
<PropertyGroup>
<TargetPlatformVersion>8.0</TargetPlatformVersion>
</PropertyGroup>
到项目文件。
由于我从 Windows 8.1 SDK C:\Program Files (x86)\Windows Kits.1\References\CommonConfiguration\Neutral\Windows.winmd
引用了 Windows.winmd 文件,可执行文件不再在 Windows 7 上启动!我双击就是这样。没有错误,没有消息。
由于我没有在网上找到任何解决方案,这就是我的问题所在:我如何做到这两点:向我的用户提供 toast 功能并制作相同的功能.exe 运行 在 Windows 7?
提前致谢!
编辑 事实证明,虽然 TargetPlatformVersion 设置为 8.0,但可执行文件无论如何都会在 Windows 7 上启动,但一旦程序尝试加载 Windows 8 库,就会崩溃:
An unhandled exception of type 'System.TypeLoadException' occurred in ToastTester.exe.
Additional information: Could not find Windows Runtime type 'Windows.UI.Notifications.ToastNotificationManager'.
在线Application.Run(new Form1());
在第 9 行的 Form1.cs 中,我有 using Windows.UI.Notifications;
在 运行 时间内避免此异常的最佳方法是什么,即使预计此可执行文件将 运行 在 Windows 7 等环境中 Windows.UI.Notifications =]命名空间肯定不可用?
我设计了自己的解决方法,以便能够支持 Windows 8 个 toast,同时防止在 运行 on Windows 7 时由于缺少库而导致应用程序崩溃。注意:我正在使用 Singleton 设计模式(成员 INSTANCE
),但您可以随时使用其他方式。
ShellLink.cs is taken from here
Win8Toaster.cs:
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Windows.Data.Xml.Dom;
using Windows.UI.Notifications;
namespace ToastManager
{
class Win8Toaster
{
public const string APPUSERMODELID = "YourCompany.YourApplicationName";
public static string ShortcutLocation;
public static ToastNotifier ToastNotifier;
private static Win8Toaster _INSTANCE = null;
public static Win8Toaster INSTANCE
{
get
{
if (_INSTANCE == null)
{
_INSTANCE = new Win8Toaster();
}
return _INSTANCE;
}
}
public Win8Toaster()
{
ShortcutLocation = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + @"\Microsoft\Windows\Start Menu\Programs\YourCompany\YourApplication.lnk");
//We need a start menu shortcut (a ShellLink object) to show toasts.
if (!File.Exists(ShortcutLocation))
{
string directory = Path.GetDirectoryName(ShortcutLocation);
if (!Directory.Exists(directory))
{
Directory.CreateDirectory(directory);
}
using (ShellLink shortcut = new ShellLink())
{
shortcut.TargetPath = System.Reflection.Assembly.GetEntryAssembly().Location;
shortcut.Arguments = "";
shortcut.AppUserModelID = APPUSERMODELID;
shortcut.Save(ShortcutLocation);
}
}
ToastNotifier = ToastNotificationManager.CreateToastNotifier(APPUSERMODELID);
}
public void ShowToast(ToastContent Content)
{
XmlDocument ToastContent = new XmlDocument();
ToastContent.LoadXml("<toast><visual><binding template=\"ToastImageAndText02\"><image id=\"1\" src=\"file:///" + Content.ImagePath + "\"/><text id=\"1\">" + Content.Text1 + "</text><text id=\"2\">" + Content.Text2 + "</text></binding></visual></toast>");
ToastNotification thisToast = new ToastNotification(ToastContent);
ToastNotifier.Show(thisToast);
}
}
}
Toaster.cs
using System;
using System.Collections.Generic;
using System.Windows.Forms;
namespace ToastManager
{
public static class Toaster
{
private static Win8Toaster ActiveToaster;
public static bool Win8ToasterAvailable = true;
public static void ShowToast(ToastContent Content)
{
if (Win8ToasterAvailable)
{
if (ActiveToaster == null)
{
if (Environment.OSVersion.Version.Major > 6 || Environment.OSVersion.Version.Major == 6 && Environment.OSVersion.Version.Minor >= 2)
{
try
{
ActiveToaster = Win8Toaster.INSTANCE;
}
catch (Exception ex)
{
Win8ToasterAvailable = false;
}
}
else
{
Win8ToasterAvailable = false;
}
}
ActiveToaster.ShowToast(Content);
}
else
{
//Use alternative notifications because Windows 8 Toasts are not available
}
}
}
//I also wrote my own toast content structure:
public class ToastContent
{
public string ImagePath, Text1, Text2;
public ToastContent(string ImagePath, string Text1, string Text2)
{
this.ImagePath = ImagePath;
this.Text1 = Text1;
this.Text2 = Text2;
}
}
}
现在您已经掌握了必要的 类,下面是如何使用它(非常简单,是吧?):
ToastManager.Toaster.ShowToast(new ToastManager.ToastContent(@"..\path\toyour\image.png", "Your Application Name", "Time: " + DateTime.Now.ToLongTimeString()));
此示例显示带有当前系统时间的 toast 通知,如果您使用的是 Windows 7.
,则不显示任何内容设计建议:
我使用 WinForms 设计了一个通知 window,它看起来与 Windows 8 中的通知类似,并模拟相同的功能,只是使用我自己的表单。或者,您也可以实现托盘图标并显示一些通知气泡。