I want to add a Product Version to a Form.[assembly: AssemblyVersion("1.0.*")]
string version = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.ToString();
This is the solution I found, and which will work. But the Version will be like "1.0.6262.26540".
Can I change the Rule or can I get the Publish Version which Visual Studio generates programmatically?
You could use ApplicationDeployment.CurrentDeployment.CurrentVersion.ToString(). However, this will only work if you are running a version of your program that was installed by the ClickOnce publisher installer (ApplicationDeployment.IsNetworkDeployed returns true).
When you start the compiled assembly directly (e.g. during debugging), you will get an InvalidDeploymentException when trying to access the CurrentDeployment property. To safeguard against this, you can use something like this:
string CurrentVersion
{
get
{
return ApplicationDeployment.IsNetworkDeployed
? ApplicationDeployment.CurrentDeployment.CurrentVersion.ToString()
: "1.0.0.0"; // Fallback version string, or retrieve from assembly as in your question
}
}
If you are not using the ClickOnce Publish function to distribute your software I am not sure that you can expect to access the "Publish Version".
using System;
using System.IO;
using System.Linq;
namespace MyAssemblyInfoPatcher
{
internal class Program
{
static void Main(string[] args)
{
if (args.Length > 0)
{
string path = args[0].ToString();
Console.WriteLine(string.Format("Current App version is set to: {0}", path));
string now_date = DateTime.Now.ToString("yyyy.MM.dd.HHmm");
if (File.Exists(path))
{
string _AssemblyVersion = string.Empty;
string _AssemblyFileVersion = string.Empty;
var lines = File.ReadLines(string.Format(path));
for (int i = 0; i < lines.Count(); i++)
{
if (lines.ElementAt(i).ToString().StartsWith("[assembly: AssemblyVersion"))
{
_AssemblyVersion = lines.ElementAt(i).ToString();
}
else if (lines.ElementAt(i).ToString().StartsWith("[assembly: AssemblyFileVersion"))
{
_AssemblyFileVersion = lines.ElementAt(i).ToString();
}
}
string _replace_assembly = File.ReadAllText(path);
if (_AssemblyVersion != string.Empty)
{
_replace_assembly = _replace_assembly.Replace(_AssemblyVersion, string.Format("[assembly: AssemblyVersion(\"{0}\")]", now_date));
}
if (_AssemblyFileVersion != string.Empty)
{
_replace_assembly = _replace_assembly.Replace(_AssemblyFileVersion, string.Format("[assembly: AssemblyFileVersion(\"{0}\")]", now_date));
}
File.WriteAllText(path, _replace_assembly);
}
}
}
}
}
Above the programs code, you can create a console application and in Project Properties > Build Events, add a "Pre-build event command line" like this: "D:\SomePath\MyAssemblyInfoPatcher.exe" "$(ProjectDir)Properties\AssemblyInfo.cs"
Related
I'm trying to Create an installer for my CAD plugin, and need to get the AutoCAD install location. but the return values of RegistryKey.GetSubKeyNames() is different from what I see in Registry Editor.
string registry_key = #"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall";
using (Microsoft.Win32.RegistryKey key = Registry.LocalMachine.OpenSubKey(registry_key))
{
foreach (string subkey_name in key.GetSubKeyNames())
{
Console.WriteLine(subkey_name);
}
}
output:
AddressBook
Autodesk Application Manager
Autodesk Content Service
Autodesk Material Library 2015
Autodesk Material Library Base Resolution Image Library 2015
Connection Manager
DirectDrawEx
DXM_Runtime
f528b707
Fontcore
...
In Registry Editor:
animizvideocn_is1
AutoCAD 2015
Autodesk 360
Connection Manager
...
AutoCAD 2015 is what i need
Your installer seems to be a 32 bit application, or at least runs as a 32 bit process.
Therefore, Windows redirects
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall
to
HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall
To access the non redirected node, follow the instructions here.
This might be not a direct answer to your question, but i had to do the same thing. I was not looking at the registry, but the Program Files directory. It will then add the netload command to the autoload lisp file. It will install a list of Plugin dlls to all installed autocad versions. This can easily be changed... Hopefully it helps.
using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
namespace AMU.AutoCAD.Update
{
public class AutoCadPluginInstaller
{
private static readonly Regex AutoloadFilenameRegex = new Regex("acad([\\d])*.lsp");
public void Install(IEnumerable<string> pluginFiles)
{
var acadDirs = this.GetAcadInstallationPaths();
var autoloadFiles = acadDirs.Select(this.GetAutoloadFile);
foreach (var autoloadFile in autoloadFiles)
this.InstallIntoAutoloadFile(autoloadFile, pluginFiles);
}
private void InstallIntoAutoloadFile(string autoloadFile, IEnumerable<string> pluginFiles)
{
try
{
var content = File.ReadAllLines(autoloadFile).ToList();
foreach (var pluginFile in pluginFiles)
{
var loadLine = this.BuildLoadLine(pluginFile);
if(!content.Contains(loadLine))
content.Add(loadLine);
}
File.WriteAllLines(autoloadFile, content);
}
catch (Exception ex)
{
//log.Log();
}
}
private string BuildLoadLine(string pluginFile)
{
pluginFile = pluginFile.Replace(#"\", "/");
return $"(command \"_netload\" \"{pluginFile}\")";
}
private IEnumerable<string> GetAcadInstallationPaths()
{
var programDirs =
Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles);
var autoDeskDir = Path.Combine(programDirs, "Autodesk");
if (!Directory.Exists(autoDeskDir))
return null;
return Directory.EnumerateDirectories(autoDeskDir)
.Where(d => d.Contains("AutoCAD"));
}
private string GetAutoloadFile(string acadDir)
{
var supportDir = Path.Combine(acadDir, "Support");
var supportFiles = Directory.EnumerateFiles(supportDir);
return supportFiles.FirstOrDefault(this.IsSupportFile);
}
private bool IsSupportFile(string path)
=> AutoloadFilenameRegex.IsMatch(Path.GetFileName(path));
}
}
(see here: https://gist.github.com/felixalmesberger/4ff8ed27f66f872face4368a13123fff)
You can use it like this:
var installer = new AutoCadPluginInstaller();
installer.Install(new [] {"Path to dll"});
Have fun.
I've read the tutorial and I'm able to generate the .cs file but it doesn't include any of my service or rpc definitions.
I've added protoc to my PATH and from inside the project directory.
protoc project1.proto --csharp_out="C:\output" --plugin=protoc-gen-grpc="c:\Users\me\.nuget\packages\grpc.tools\1.8.0\tools\windows_x64\grpc_csharp_plugin.exe"
No errors output in console
You need to add the --grpc_out command line option, e.g. add
--grpc_out="C:\output\"
Note that it won't write any files if you don't have any services.
Here's a complete example. From a root directory, create:
An empty output directory
A tools directory with protoc.exe and grpc_csharp_plugin.exe
A protos directory with test.proto as shown below:
test.proto:
syntax = "proto3";
service StackOverflowService {
rpc GetAnswer(Question) returns (Answer);
}
message Question {
string text = 1;
string user = 2;
repeated string tags = 3;
}
message Answer {
string text = 1;
string user = 2;
}
Then run (all on one line; I've broken it just for readability here):
tools\protoc.exe -I protos protos\test.proto --csharp_out=output
--grpc_out=output --plugin=protoc-gen-grpc=tools\grpc_csharp_plugin.exe
In the output directory, you'll find Test.cs and TestGrpc.cs
Just an idle comment here for other that find this, the documentation about this is terribly out of date and just flat out wrong.
Installing Grpc.Tools does not install anything in a packages folder; that is legacy behaviour which is no longer true even on windows.
When you install Grpc.Tools it will be hidden away in your local package cache, which you can see by calling:
$ dotnet nuget locals all --list
info : http-cache: /Users/doug/.local/share/NuGet/v3-cache
info : global-packages: /Users/doug/.nuget/packages/
info : temp: /var/folders/xx/s2hnzbrj3yn4hp1bg8q9gb_m0000gn/T/NuGetScratch
The binaries you want will be in one of these folders.
The easiest way to do this is to download the Grpc.Tools package directly from nuget, and install it locally.
I've hacked up this little helper script to do that, which works on windows/mac/linux, which may ease the difficulty of getting starting with this for others:
using System;
using System.Diagnostics;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Net.Http;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Threading.Tasks;
using Mono.Unix;
namespace BuildProtocol
{
public class Program
{
private const string ToolsUrl = "https://www.nuget.org/api/v2/package/Grpc.Tools/";
private const string Service = "Greeter";
private static string ProtocolPath = Path.Combine("..", "protos");
private static string Protocol = Path.Combine(ProtocolPath, "helloworld.proto");
private static string Output = Path.Combine("..", "Greeter");
public static void Main(string[] args)
{
RequireTools().Wait();
var protoc = ProtocPath();
var plugin = ProtocPluginPath();
Console.WriteLine($"Using: {protoc}");
Console.WriteLine($"Using: {plugin}");
var command = new string[]
{
$"-I{ProtocolPath}",
$"--csharp_out={Output}",
$"--grpc_out={Output}",
$"--plugin=protoc-gen-grpc=\"{plugin}\"",
Protocol,
};
Console.WriteLine($"Exec: {protoc} {string.Join(' ', command)}");
var process = new Process
{
StartInfo = new ProcessStartInfo
{
UseShellExecute = false,
FileName = protoc,
Arguments = string.Join(' ', command)
}
};
process.Start();
process.WaitForExit();
Console.WriteLine($"Completed status: {process.ExitCode}");
}
public static async Task RequireTools()
{
if (!Directory.Exists("Tools"))
{
Console.WriteLine("No local tools found, downloading binaries from nuget...");
Directory.CreateDirectory("Tools");
await DownloadTools();
ExtractTools();
}
}
private static void ExtractTools()
{
ZipFile.ExtractToDirectory(Path.Combine("Tools", "tools.zip"), Path.Combine("Tools", "bin"));
}
private static async Task DownloadTools()
{
using (var client = new HttpClient())
{
Console.WriteLine($"Fetching: {ToolsUrl}");
using (var result = await client.GetAsync(ToolsUrl))
{
if (!result.IsSuccessStatusCode) throw new Exception($"Unable to download tools ({result.StatusCode}), check URL");
var localArchive = Path.Combine("Tools", "tools.zip");
Console.WriteLine($"Saving to: {localArchive}");
File.WriteAllBytes(localArchive, await result.Content.ReadAsByteArrayAsync());
}
}
}
private static string ProtocPath()
{
var path = Path.Combine("Tools", "bin", "tools", DetermineArch(), "protoc");
RequireExecutablePermission(path);
return WithExeExtensionIfRequired(path);
}
private static string ProtocPluginPath()
{
var path = Path.Combine("Tools", "bin", "tools", DetermineArch(), "grpc_csharp_plugin");
RequireExecutablePermission(path);
return WithExeExtensionIfRequired(path);
}
private static void RequireExecutablePermission(string path)
{
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) return;
Console.WriteLine($"Ensuring +x on {path}");
var unixFileInfo = new UnixFileInfo(path);
unixFileInfo.FileAccessPermissions = FileAccessPermissions.UserRead | FileAccessPermissions.UserWrite | FileAccessPermissions.UserExecute;
}
private static string WithExeExtensionIfRequired(string path)
{
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
path += ".exe";
}
return path;
}
private static string DetermineArch()
{
var arch = RuntimeInformation.OSArchitecture;
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
return WithArch("windows_", arch);
}
if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
{
return WithArch("macosx_", arch);
}
if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
{
return WithArch("linux_", arch);
}
throw new Exception("Unable to determine runtime");
}
private static string WithArch(string platform, Architecture arch)
{
switch (arch)
{
case Architecture.X64:
return $"{platform}x86";
case Architecture.X86:
return $"{platform}x64";
default:
throw new ArgumentOutOfRangeException(nameof(arch), arch, null);
}
}
}
}
the following approach helped me :
Create a gRPC client and server in ASP.NET Core
in project, where .proto file located, edit the .csproj file
<ItemGroup>
....
<Protobuf Include="Shipping.proto" GrpcServices="Server" />
</ItemGroup>
rebuild the project, the all necessary .cs files will be added automaticaly
\obj\Debug\[TARGET_FRAMEWORK]\Shipping.cs
\obj\Debug\[TARGET_FRAMEWORK]\ShippingGrpc.cs
This is my first Q# program and i'm following this getting started link.https://learn.microsoft.com/en-us/quantum/quantum-writeaquantumprogram?view=qsharp-preview
Error is
The name 'BellTest' does not exist in the current context
but its defined in the Bell.cs
I followed the steps and when building its having errors. I'm not sure how to import the operations from .qs file to driver c# file as this error looks like it can't find that operation.
Any help is really appreciated
Here is the code
Driver.cs
using Microsoft.Quantum.Simulation.Core;
using Microsoft.Quantum.Simulation.Simulators;
namespace Quantum.Bell
{
class Driver
{
static void Main(string[] args)
{
using (var sim = new QuantumSimulator())
{
// Try initial values
Result[] initials = new Result[] { Result.Zero, Result.One };
foreach (Result initial in initials)
{
var res = BellTest.Run(sim, 1000, initial).Result;
var (numZeros, numOnes) = res;
System.Console.WriteLine(
$"Init:{initial,-4} 0s={numZeros,-4} 1s={numOnes,-4}");
}
}
System.Console.WriteLine("Press any key to continue...");
System.Console.ReadKey();
}
}
}
Bell.qs
namespace Quantum.Bell
{
open Microsoft.Quantum.Primitive;
open Microsoft.Quantum.Canon;
operation Set (desired:Result,q1:Qubit) : ()
{
body
{
let current = M(q1);
if (desired != current)
{
X(q1);
}
}
}
operation BellTest (count : Int, initial: Result) : (Int,Int)
{
body
{
mutable numOnes = 0;
using (qubits = Qubit[1])
{
for (test in 1..count)
{
Set (initial, qubits[0]);
let res = M (qubits[0]);
// Count the number of ones we saw:
if (res == One)
{
set numOnes = numOnes + 1;
}
}
Set(Zero, qubits[0]);
}
// Return number of times we saw a |0> and number of times we saw a |1>
return (count-numOnes, numOnes);
}
}
}
I also got the same error, but I was able to do it by pressing the F5 key.
Perhaps the Visual Studio editor is not yet fully support to the .qs file.
Namespace sharing does not seem to be working properly between .cs file and .qs file.
I was able to execute using your code in my development environment.
--
IDE: Visual Studio Community 2017 (Version 15.5.2)
Dev Kit: Microsoft Quantum Development Kit (0 and 1)
I engage the same problem in microsoft.quantum.development.kit/0.3.1811.203-preview version.
The BellTest operation cannot recognised by VSC Pic of VSCode
What I do is,
save all but keep VSCode open
go to directory and delete anything in bin/ obj/ by /bin/rm -rf bin obj
dotnet run
you go back to check VSCode, the BellTest recognised by VSC now.
I have an unusual situation here.
Problem
I'm using Visual studio (VS) to write scripts to use in-game in the game Space Engineers.
The problem is that you only use a portion of the code from the file in-game. (I.E, Ctrl+A wont do). So selecting the correct portion is tedious.
I want to streamline the process of copying the desired code in VS and pasting it in Space Engineers.
The idea is to trim all unnecessary white space (there's a character limit) and copy to clipboard when pressing run in VS.
Where I'm at
I've found that you can make your own build configuration and use the "Pre-build event command line" to run something custom. The idea is to make a simple console application that does what I described above. But I don't know how to get the correct file to send to said application.
Am I on the right track? How do I send the desired file to the trimming application? Is there a better way?
Edit:
This is what I had in mind when I said "simple console application".
It does everything I needed it to do (trimming white-space and adding a portion of the code to clipboard). Only thing missing is that I have to specify the file name I want it to use. Which isn't important, it would just be nice.
using System;
using System.Windows.Forms;
namespace TrimFileToClipboard
{
class Program
{
[STAThread()]
static void Main(string[] args)
{
string startString = (args.Length > 1) ? "#region " + args[1] : "#region in-game";
string line;
string trimmed = "";
bool read = false;
int depth = 0;
System.IO.StreamReader file = new System.IO.StreamReader(args[0]);
while ((line = file.ReadLine()) != null)
{
if (!read && line.Contains(startString)) read = true;
else if (read && line.Contains("#region")) depth++;
else if (read && line.Contains("#endregion"))
{
if (depth == 0) break;
else if (depth < 0)
{
Console.WriteLine("There's something wrong with your #regions. Please edit the file.");
Console.ReadLine();
Environment.Exit(0);
}
else depth--;
}
else if (read) trimmed += line.Trim() + "\n";
}
file.Close();
Clipboard.SetText(trimmed);
}
}
}
It can be used by adding
"<path>\TrimFileToClipboard.exe" "$(ProjectDir)<classname>.cs"
to Pre-build event command line, in the project properties/Build events. Where <path> is the path to the application above and <classname> is the file you want to process.
Maybe I should post this part as an answer but I don't know if it's a decent approach or an ugly hack.
Instead of coping the code to the clipboard, I save it directly inside the game as saved workshop script with this simple C# console application.
The SE script I edit using VS has the comments \\script-begin and \\script-end to tell the application where to look for the actual code that needs to be in the programmable block.
After the execution the script will be available at the local workshop. It makes it very easy to work with the SE scripts, whenever I make a change using VS, I run the console application again and the script will be updated inside the game.
internal class Program
{
private static void Main(string[] args)
{
String[] InputLines, outputLines;
Int32 scriptBegin = 0, scriptEnd = 0;
String scriptName = args[0];
String inputPath = "C:\\Users\\hfand\\source\\repos\\se-scripts\\" + scriptName + ".cs";
if (File.Exists(inputPath))
{
InputLines = File.ReadAllLines(inputPath);
for (int i = 0; i < InputLines.Length; i++)
{
if (InputLines[i].Contains("script-begin"))
{
scriptBegin = i + 1;
}
if (InputLines[i].Contains("script-end"))
{
scriptEnd = i - 1;
}
}
outputLines = new List<string>(InputLines).GetRange(scriptBegin, scriptEnd - scriptBegin + 1).ToArray();
for (int i = 0; i < outputLines.Length; i++)
{
if (outputLines[i].Length >= 8)
{
outputLines[i] = outputLines[i].Substring(8);
}
}
String outputPath = "C:\\Users\\hfand\\AppData\\Roaming\\SpaceEngineers\\IngameScripts\\local\\" + scriptName;
if (Directory.Exists(outputPath))
{
File.WriteAllLines(outputPath + "\\Script.cs", outputLines);
}
else
{
Directory.CreateDirectory(outputPath);
File.WriteAllLines(outputPath + "\\Script.cs", outputLines);
}
Console.WriteLine(scriptName + " sincronizado");
}
else
{
Console.WriteLine("Arquivo \"" + inputPath + "\" não encontrado");
}
}
}
Here is an example of how the code in VS should look like
using System;
using System.Text;
using System.Collections;
using System.Collections.Generic;
using VRageMath;
using VRage.Game;
using Sandbox.ModAPI.Interfaces;
using Sandbox.ModAPI.Ingame;
using Sandbox.Game.EntityComponents;
using VRage.Game.Components;
using VRage.Collections;
using VRage.Game.ObjectBuilders.Definitions;
using VRage.Game.ModAPI.Ingame;
using SpaceEngineers.Game.ModAPI.Ingame;
namespace BlankScript
{
public class Program : MyGridProgram
{
//script-begin
public Program()
{
}
public void Save()
{
}
public void Main(string argument, UpdateType updateSource)
{
}
//script-end
}
}
You can write a C# command with my Visual Commander extension that gets active file path in Visual Studio as DTE.ActiveWindow.Document.FullName and then runs your file.ReadLine() loop over it and calls Clipboard.SetText(trimmed) at the end. See for example Copy current file, line, method sample code.
I developed a .NET windows application which worked both on Windows 7 and 8.1. Then I added the Toast notification feature that came with Windows 8 (from this question: How can I use the Windows.UI namespace from a regular (Non-Store) Win32 .NET application?).
This also worked, I just had to add:
<PropertyGroup>
<TargetPlatformVersion>8.0</TargetPlatformVersion>
</PropertyGroup>
to the project file.
As I referenced the Windows.winmd file from the Windows 8.1 SDK C:\Program Files (x86)\Windows Kits\8.1\References\CommonConfiguration\Neutral\Windows.winmd, the executable does not start on Windows 7 anymore! I double-click and that's it. No errors, no messages.
As I did not find any solution online, that's where my question comes up: How do I manage to do both: Offer the toast feature to my users AND make the same .exe run on Windows 7?
Thank you in advance!
EDIT
It turns out that though TargetPlatformVersion is set to 8.0, the executable starts on Windows 7 anyway, but crashes as soon as the program tries to load the Windows 8 libraries:
An unhandled exception of type 'System.TypeLoadException' occurred in ToastTester.exe.
Additional information: Could not find Windows Runtime type 'Windows.UI.Notifications.ToastNotificationManager'.
on line Application.Run(new Form1());
In Form1.cs in line 9 I've got using Windows.UI.Notifications;
What is the best way to avoid this exception during runtime, even though it is expected that this executable will run in environments like Windows 7 where the Windows.UI.Notifications namespace is definitely not available?
I designed my own workaround for being able to support Windows 8 toasts and at the same time prevent application crashes due to missing libraries when running on Windows 7. Note: I am using the Singleton design pattern (member INSTANCE), but you can always do it otherwise.
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;
}
}
}
Now that you've got the necessary classes, here is how to use it (pretty simple, huh?):
ToastManager.Toaster.ShowToast(new ToastManager.ToastContent(#"..\path\toyour\image.png", "Your Application Name", "Time: " + DateTime.Now.ToLongTimeString()));
This example shows a toast notification with the current system time or nothing if you are on Windows 7.
A design suggestion:
I used WinForms to design a notification window which looks similar to that in Windows 8 and simulates the same functions, just with my own forms. Alternatively you can also implement a tray icon and show some notification bubbles.