Using visual studio 2013 built in message box via DTE object - visual-studio

I'm developing visual studio project template.
During the template installation I perform some long operations that I want to let the user know about.
I've already seen the DTE statusbar progress method but I prefer output the message in visual studio built in message box.
Is it possible?

Ok, I think I got it.
The assemblies:
Microsoft.VisualStudio.OLE.Interop
Microsoft.VisualStudio.Shell.12.0
Microsoft.VisualStudio.Shell.Interop.10.0
In the using statements:
using IOleServiceProvider = Microsoft.VisualStudio.OLE.Interop.IServiceProvider;
The code:
private IVsThreadedWaitDialog2 _progressDialog = null;
private void StartProgressDialog(string operation, string statusBarText, int total)
{
if (_progressDialog == null)
{
IOleServiceProvider oleServiceProvider = _dte as IOleServiceProvider;
IVsThreadedWaitDialogFactory dialogFactory = new ServiceProvider(oleServiceProvider).GetService(
typeof(SVsThreadedWaitDialogFactory)) as IVsThreadedWaitDialogFactory;
IVsThreadedWaitDialog2 dialog = null;
if (dialogFactory != null)
{
dialogFactory.CreateInstance(out dialog);
_progressDialog = dialog;
}
}
if(_progressDialog != null)
{
_progressDialog.StartWaitDialogWithPercentageProgress("Wait Dialogue", operation, null, null, statusBarText, false, 0, total, 0);
}
}
private void TerminatePreogressDialog()
{
if (_progressDialog != null)
{
int canceled;
_progressDialog.EndWaitDialog(out canceled);
}
}
private void UpdateLongOperationMessage(string operation, string progressMessage, int step, int total)
{
if (_progressDialog != null)
{
bool canceled;
_progressDialog.UpdateProgress(operation, progressMessage, progressMessage, step, total, true, out canceled);
}
}

Related

How to switch desktop to the next one like { win+ctrl+ ->} in win10? [duplicate]

I love that Windows 10 now has support for virtual desktops built in, but I have some features that I'd like to add/modify (e.g., force a window to appear on all desktops, launch the task view with a hotkey, have per-monitor desktops, etc.)
I have searched for applications and developer references to help me customize my desktops, but I have had no luck.
Where should I start? I am looking for Windows API functions (ideally, that are callable from a C# application) that will give me programmatic access to manipulate virtual desktops and the windows therein.
The Windows SDK Support Team Blog posted a C# demo to switch Desktops via IVirtualDesktopManager:
[ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("a5cd92ff-29be-454c-8d04-d82879fb3f1b")]
[System.Security.SuppressUnmanagedCodeSecurity]
public interface IVirtualDesktopManager
{
[PreserveSig]
int IsWindowOnCurrentVirtualDesktop(
[In] IntPtr TopLevelWindow,
[Out] out int OnCurrentDesktop
);
[PreserveSig]
int GetWindowDesktopId(
[In] IntPtr TopLevelWindow,
[Out] out Guid CurrentDesktop
);
[PreserveSig]
int MoveWindowToDesktop(
[In] IntPtr TopLevelWindow,
[MarshalAs(UnmanagedType.LPStruct)]
[In]Guid CurrentDesktop
);
}
[ComImport, Guid("aa509086-5ca9-4c25-8f95-589d3c07b48a")]
public class CVirtualDesktopManager
{
}
public class VirtualDesktopManager
{
public VirtualDesktopManager()
{
cmanager = new CVirtualDesktopManager();
manager = (IVirtualDesktopManager)cmanager;
}
~VirtualDesktopManager()
{
manager = null;
cmanager = null;
}
private CVirtualDesktopManager cmanager = null;
private IVirtualDesktopManager manager;
public bool IsWindowOnCurrentVirtualDesktop(IntPtr TopLevelWindow)
{
int result;
int hr;
if ((hr = manager.IsWindowOnCurrentVirtualDesktop(TopLevelWindow, out result)) != 0)
{
Marshal.ThrowExceptionForHR(hr);
}
return result != 0;
}
public Guid GetWindowDesktopId(IntPtr TopLevelWindow)
{
Guid result;
int hr;
if ((hr = manager.GetWindowDesktopId(TopLevelWindow, out result)) != 0)
{
Marshal.ThrowExceptionForHR(hr);
}
return result;
}
public void MoveWindowToDesktop(IntPtr TopLevelWindow, Guid CurrentDesktop)
{
int hr;
if ((hr = manager.MoveWindowToDesktop(TopLevelWindow, CurrentDesktop)) != 0)
{
Marshal.ThrowExceptionForHR(hr);
}
}
}
it includes the API to detect on which desktop the Window is shown and it can switch and move a Windows the a Desktop.
Programmatic access to the virtual desktop feature is very limited, as Microsoft has only exposed the IVirtualDesktopManager COM interface. It does provide two key functions:
IVirtualDesktopManager::GetWindowDesktopId allows you to retrieve the ID of a virtual desktop, based on a window that is already assigned to that desktop.
IVirtualDesktopManager::MoveWindowToDesktop allows you to move a window to a specific virtual desktop.
Unfortunately, this is not nearly enough to accomplish anything useful. I've written some C# code based on the reverse-engineering work done by NickoTin. I can't read much of the Russian in his blog post, but his C++ code was pretty accurate.
I do need to emphasize that this code is not something you want to commit to in a product. Microsoft always feels free to change undocumented APIs whenever they feel like it. And there is a runtime risk as well: this code does not necessarily interact well when the user is tinkering with the virtual desktops. Always keep in mind that a virtual desktop can appear and disappear at any time, completely out of sync with your code.
To use the code, create a new C# class library project. I'll first post ComInterop.cs, it contains the COM interface declarations that match NickoTin's C++ declarations:
using System;
using System.Runtime.InteropServices;
namespace Windows10Interop {
internal static class Guids {
public static readonly Guid CLSID_ImmersiveShell =
new Guid(0xC2F03A33, 0x21F5, 0x47FA, 0xB4, 0xBB, 0x15, 0x63, 0x62, 0xA2, 0xF2, 0x39);
public static readonly Guid CLSID_VirtualDesktopManagerInternal =
new Guid(0xC5E0CDCA, 0x7B6E, 0x41B2, 0x9F, 0xC4, 0xD9, 0x39, 0x75, 0xCC, 0x46, 0x7B);
public static readonly Guid CLSID_VirtualDesktopManager =
new Guid("AA509086-5CA9-4C25-8F95-589D3C07B48A");
public static readonly Guid IID_IVirtualDesktopManagerInternal =
new Guid("AF8DA486-95BB-4460-B3B7-6E7A6B2962B5");
public static readonly Guid IID_IVirtualDesktop =
new Guid("FF72FFDD-BE7E-43FC-9C03-AD81681E88E4");
}
[ComImport]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
[Guid("FF72FFDD-BE7E-43FC-9C03-AD81681E88E4")]
internal interface IVirtualDesktop {
void notimpl1(); // void IsViewVisible(IApplicationView view, out int visible);
Guid GetId();
}
[ComImport]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
[Guid("AF8DA486-95BB-4460-B3B7-6E7A6B2962B5")]
internal interface IVirtualDesktopManagerInternal {
int GetCount();
void notimpl1(); // void MoveViewToDesktop(IApplicationView view, IVirtualDesktop desktop);
void notimpl2(); // void CanViewMoveDesktops(IApplicationView view, out int itcan);
IVirtualDesktop GetCurrentDesktop();
void GetDesktops(out IObjectArray desktops);
[PreserveSig]
int GetAdjacentDesktop(IVirtualDesktop from, int direction, out IVirtualDesktop desktop);
void SwitchDesktop(IVirtualDesktop desktop);
IVirtualDesktop CreateDesktop();
void RemoveDesktop(IVirtualDesktop desktop, IVirtualDesktop fallback);
IVirtualDesktop FindDesktop(ref Guid desktopid);
}
[ComImport]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
[Guid("a5cd92ff-29be-454c-8d04-d82879fb3f1b")]
internal interface IVirtualDesktopManager {
int IsWindowOnCurrentVirtualDesktop(IntPtr topLevelWindow);
Guid GetWindowDesktopId(IntPtr topLevelWindow);
void MoveWindowToDesktop(IntPtr topLevelWindow, ref Guid desktopId);
}
[ComImport]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
[Guid("92CA9DCD-5622-4bba-A805-5E9F541BD8C9")]
internal interface IObjectArray {
void GetCount(out int count);
void GetAt(int index, ref Guid iid, [MarshalAs(UnmanagedType.Interface)]out object obj);
}
[ComImport]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
[Guid("6D5140C1-7436-11CE-8034-00AA006009FA")]
internal interface IServiceProvider10 {
[return: MarshalAs(UnmanagedType.IUnknown)]
object QueryService(ref Guid service, ref Guid riid);
}
}
Next is Desktop.cs. It contains the friendly C# classes that you can use in your code:
using System;
using System.Runtime.InteropServices;
namespace Windows10Interop
{
public class Desktop {
public static int Count {
// Returns the number of desktops
get { return DesktopManager.Manager.GetCount(); }
}
public static Desktop Current {
// Returns current desktop
get { return new Desktop(DesktopManager.Manager.GetCurrentDesktop()); }
}
public static Desktop FromIndex(int index) {
// Create desktop object from index 0..Count-1
return new Desktop(DesktopManager.GetDesktop(index));
}
public static Desktop FromWindow(IntPtr hWnd) {
// Creates desktop object on which window <hWnd> is displayed
Guid id = DesktopManager.WManager.GetWindowDesktopId(hWnd);
return new Desktop(DesktopManager.Manager.FindDesktop(ref id));
}
public static Desktop Create() {
// Create a new desktop
return new Desktop(DesktopManager.Manager.CreateDesktop());
}
public void Remove(Desktop fallback = null) {
// Destroy desktop and switch to <fallback>
var back = fallback == null ? DesktopManager.GetDesktop(0) : fallback.itf;
DesktopManager.Manager.RemoveDesktop(itf, back);
}
public bool IsVisible {
// Returns <true> if this desktop is the current displayed one
get { return object.ReferenceEquals(itf, DesktopManager.Manager.GetCurrentDesktop()); }
}
public void MakeVisible() {
// Make this desktop visible
DesktopManager.Manager.SwitchDesktop(itf);
}
public Desktop Left {
// Returns desktop at the left of this one, null if none
get {
IVirtualDesktop desktop;
int hr = DesktopManager.Manager.GetAdjacentDesktop(itf, 3, out desktop);
if (hr == 0) return new Desktop(desktop);
else return null;
}
}
public Desktop Right {
// Returns desktop at the right of this one, null if none
get {
IVirtualDesktop desktop;
int hr = DesktopManager.Manager.GetAdjacentDesktop(itf, 4, out desktop);
if (hr == 0) return new Desktop(desktop);
else return null;
}
}
public void MoveWindow(IntPtr handle) {
// Move window <handle> to this desktop
DesktopManager.WManager.MoveWindowToDesktop(handle, itf.GetId());
}
public bool HasWindow(IntPtr handle) {
// Returns true if window <handle> is on this desktop
return itf.GetId() == DesktopManager.WManager.GetWindowDesktopId(handle);
}
public override int GetHashCode() {
return itf.GetHashCode();
}
public override bool Equals(object obj) {
var desk = obj as Desktop;
return desk != null && object.ReferenceEquals(this.itf, desk.itf);
}
private IVirtualDesktop itf;
private Desktop(IVirtualDesktop itf) { this.itf = itf; }
}
internal static class DesktopManager {
static DesktopManager() {
var shell = (IServiceProvider10)Activator.CreateInstance(Type.GetTypeFromCLSID(Guids.CLSID_ImmersiveShell));
Manager = (IVirtualDesktopManagerInternal)shell.QueryService(Guids.CLSID_VirtualDesktopManagerInternal, Guids.IID_IVirtualDesktopManagerInternal);
WManager = (IVirtualDesktopManager)Activator.CreateInstance(Type.GetTypeFromCLSID(Guids.CLSID_VirtualDesktopManager));
}
internal static IVirtualDesktop GetDesktop(int index) {
int count = Manager.GetCount();
if (index < 0 || index >= count) throw new ArgumentOutOfRangeException("index");
IObjectArray desktops;
Manager.GetDesktops(out desktops);
object objdesk;
desktops.GetAt(index, Guids.IID_IVirtualDesktop, out objdesk);
Marshal.ReleaseComObject(desktops);
return (IVirtualDesktop)objdesk;
}
internal static IVirtualDesktopManagerInternal Manager;
internal static IVirtualDesktopManager WManager;
}
}
And finally a little test WinForms project that I used to test the code. Just drop 4 buttons on a form and name them buttonLeft/Right/Create/Destroy:
using Windows10Interop;
using System.Diagnostics;
...
public partial class Form1 : Form {
public Form1() {
InitializeComponent();
}
private void buttonRight_Click(object sender, EventArgs e) {
var curr = Desktop.FromWindow(this.Handle);
Debug.Assert(curr.Equals(Desktop.Current));
var right = curr.Right;
if (right == null) right = Desktop.FromIndex(0);
if (right != null) {
right.MoveWindow(this.Handle);
right.MakeVisible();
this.BringToFront();
Debug.Assert(right.IsVisible);
}
}
private void buttonLeft_Click(object sender, EventArgs e) {
var curr = Desktop.FromWindow(this.Handle);
Debug.Assert(curr.Equals(Desktop.Current));
var left = curr.Left;
if (left == null) left = Desktop.FromIndex(Desktop.Count - 1);
if (left != null) {
left.MoveWindow(this.Handle);
left.MakeVisible();
this.BringToFront();
Debug.Assert(left.IsVisible);
}
}
private void buttonCreate_Click(object sender, EventArgs e) {
var desk = Desktop.Create();
desk.MoveWindow(this.Handle);
desk.MakeVisible();
Debug.Assert(desk.IsVisible);
Debug.Assert(desk.Equals(Desktop.Current));
}
private void buttonDestroy_Click(object sender, EventArgs e) {
var curr = Desktop.FromWindow(this.Handle);
var next = curr.Left;
if (next == null) next = curr.Right;
if (next != null && next != curr) {
next.MoveWindow(this.Handle);
curr.Remove(next);
Debug.Assert(next.IsVisible);
}
}
}
The only real quirk I noticed while testing this is that moving a window from one desktop to another can move it to the bottom of the Z-order when you first switch the desktop, then move the window. No such problem if you do it the other way around.
There is this guy that made a application to map keyboard shorcut to move a window between virtual desktop.
https://github.com/Grabacr07/SylphyHorn
(I use it every day )
He has a blog where he explain what he did
http://grabacr.net/archives/5701 ( you can use google translate it is in japanese)
He in fact used the same api mantionned in the Alberto Tostado response.
http://www.cyberforum.ru/blogs/105416/blog3671.html
and the api can be found on his github https://github.com/Grabacr07/VirtualDesktop
The api is really simple to use BUT it seems impossible to move a window from another process.
public static bool MoveToDesktop(IntPtr hWnd, VirtualDesktop virtualDesktop)
{
ThrowIfNotSupported();
int processId;
NativeMethods.GetWindowThreadProcessId(hWnd, out processId);
if (Process.GetCurrentProcess().Id == processId) // THAT LINE
{
var guid = virtualDesktop.Id;
VirtualDesktop.ComManager.MoveWindowToDesktop(hWnd, ref guid);
return true;
}
return false;
}
To workaround this problem they made another implementation that they use alongside the one in the russian blog
if (VirtualDesktopHelper.MoveToDesktop(hWnd, right) //<- the one in the russian blog
|| this.helper.MoveWindowToDesktop(hWnd, right.Id)) <- the second implementation
The second implementation can be found here: https://github.com/tmyt/VDMHelper
This one can move a window from another process to another desktop. BUT it is buggy right now. For exemple when i try to move some window like google chrome it crash.
So this is the result of my research. I m rigth now trying to make a StickyWindow feature with these api.
I fear that all about "Virtual desktops" in Windows 10 is undocumented, but in a Russian page I've seen documented the interfaces. I don't speak Russian but seems that they have used reversed engineering. Anyway, the code is very clear (Thanks to them!).
Keep an eye here:
http://www.cyberforum.ru/blogs/105416/blog3671.html
I've been trying to see if the old API's CreateDesktop, OpenDesktop, etc... is linked to the new Virtual-Desktops, but no way...
The interfaces work with the final production release of Windows 10 (2015-05-08), but you shouldn't use them in a real wide distributed application until Microsoft documents them. Too much risk.
Regards.

Installation progress status messages from InstallShield Suite Installer

I have my own Updater.exe that launches the InstallShield Suite Installer (which is embedded with two other InstallShield MSIs). I would like to get the installation progress status messages from Suite Installer and show in my Updater.exe UI.
Is it possible to poll/ping the installer to get the installation status message? (Like staging, installing msi1, installing msi2, configuring, install complete).
I am using .NET Framework 4.5+ in my installer as a prerequisite, Installshield version 2016, wiX toolset for custom actions.
InstallShield 2016 do not have any out of the box features to get the status messages while the installation is in progress.
I end up writing my own tool to monitor installshield property values in debug log that generates with debuglog parameters.
InstallShield Installer Debug Logs:
syntax: Installer.exe /debuglog"logfilepath"
example: installer.exe /debuglog"c:\users\test.user\desktop\debuglog.log"
InstallShield sets three different status types viz; 'ISProgressSummary', 'ISInstallStatus' and 'ISParcelStatus' and logs into debug logs.
Sample installshield debug log entries are:
9-23-2019[10:40:56 AM]: Engine: property 'ISProgressSummary' value now 'The program features you selected are being installed.'
9-23-2019[10:41:12 AM]: Engine: property 'ISInstallStatus' value now 'Installing package Microsoft Visual C++ 2012 Update 4 Redistributable Package (x86)'
9-23-2019[10:41:17 AM]: Engine: property 'ISParcelStatus' value now 'Computing space requirements'
Below C# code monitors debug log and invokes an event handler. You create an object of below class and send the 'statusType' you want to monitor. statusType can be ISProgressSummary, ISInstallStatus, ISParcelStatus
public class LogFileMonitorLineEventArgs : EventArgs
{
public string Line { get; set; }
}
public class LogFileMonitor
{
public EventHandler<LogFileMonitorLineEventArgs> OnLine;
readonly string _path;
readonly string _delimiter;
readonly string _statusType;
Timer _timer;
long _currentSize;
bool _isCheckingLog;
protected bool StartCheckingLog()
{
lock (_timer)
{
if (_isCheckingLog)
return true;
_isCheckingLog = true;
return false;
}
}
protected void DoneCheckingLog()
{
lock (_timer)
_isCheckingLog = false;
}
public LogFileMonitor(string path, string delimiter = "\n", string statusType = "")
{
_path = path;
_delimiter = delimiter;
_statusType = statusType;
}
public void Start()
{
_currentSize = new FileInfo(_path).Length;
_timer = new Timer(1000);
_timer.Elapsed += CheckLog;
_timer.AutoReset = true;
_timer.Start();
}
private void CheckLog(object s, ElapsedEventArgs e)
{
if (!StartCheckingLog()) return;
try
{
var newSize = new FileInfo(_path).Length;
if (_currentSize == newSize)
return;
using (FileStream stream = File.Open(_path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
using (StreamReader sr = new StreamReader(stream, Encoding.Unicode))
{
sr.BaseStream.Seek(_currentSize, SeekOrigin.Begin);
var newData = sr.ReadToEnd();
if (!newData.EndsWith(_delimiter))
{
if (newData.IndexOf(_delimiter, StringComparison.Ordinal) == -1)
{
newData = string.Empty;
}
else
{
var pos = newData.LastIndexOf(_delimiter, StringComparison.Ordinal) + _delimiter.Length;
newData = newData.Substring(0, pos);
}
}
string[] lines = newData.Split(new[] { _delimiter }, StringSplitOptions.RemoveEmptyEntries);
string lastInstallStatus = string.Empty;
foreach (string line in lines)
{
if (line.Contains(_statusType))
{
lastInstallStatus = line;
OnLine?.Invoke(this, new LogFileMonitorLineEventArgs { Line = lastInstallStatus });
}
}
}
_currentSize = newSize;
}
catch (Exception)
{
}
DoneCheckingLog();
}
public void Stop()
{
_timer?.Stop();
}
}

How to Change Ctrl+C in Visual Studio 2017 to Copy Word, Not Entire Line

This question is similar to Disabling single line copy in Visual Studio, except that I'm wanting to change it to just copy the word the cursor is on, if nothing is not selected. If it's on white space, sure, I don't care, copy the line, but 99% I'm trying to copy a word, not the line Is this possible?
To copy the word the caret is on, you can assign a shortcut to the following Visual Commander (developed by me) command (language C#):
public class C : VisualCommanderExt.ICommand
{
public void Run(EnvDTE80.DTE2 DTE, Microsoft.VisualStudio.Shell.Package package)
{
this.DTE = DTE;
EnvDTE.TextSelection ts = TryGetFocusedDocumentSelection();
if (ts != null && ts.IsEmpty)
CopyWord(ts);
else if (IsCommandAvailable("Edit.Copy"))
DTE.ExecuteCommand("Edit.Copy");
}
private void CopyWord(EnvDTE.TextSelection ts)
{
EnvDTE.EditPoint left = ts.ActivePoint.CreateEditPoint();
left.WordLeft();
EnvDTE.EditPoint right = ts.ActivePoint.CreateEditPoint();
right.WordRight();
System.Windows.Clipboard.SetText(left.GetText(right));
}
private EnvDTE.TextSelection TryGetFocusedDocumentSelection()
{
try
{
return DTE.ActiveWindow.Document.Selection as EnvDTE.TextSelection;
}
catch(System.Exception)
{
}
return null;
}
private bool IsCommandAvailable(string commandName)
{
EnvDTE80.Commands2 commands = DTE.Commands as EnvDTE80.Commands2;
if (commands == null)
return false;
EnvDTE.Command command = commands.Item(commandName, 0);
if (command == null)
return false;
return command.IsAvailable;
}
private EnvDTE80.DTE2 DTE;
}

How can I tell a running Visual Studio 2012 instance to run a certain macro from within a VBScript invoked by another application?

I have two different solutions (A and B) open inside two different instances of the Visual Studio 2012.
I want to write two macros - MacroA and MacroB. MacroA should be run on the VS instance with the solution A and MacroB - on the VS instance with the solution B.
Here is what I want to do from MacroA:
Start a Stopwatch
Trigger the build of the current solution (which is A)
Once the build is complete stop the Stopwatch and output the elapsed time
Tell the other VS instance to run MacroB
Here is what I want to do from MacroB:
Start a Stopwatch
Trigger the build of the current solution (which is B)
Stop the Stopwatch and output the elapsed time
Please, note that I perfectly aware of how to build a solution on the command line using devenv (or msbuild). I explicitly want to build from the IDE.
Is it possible to do what I want?
Finally solved this problem with the help of the following resources:
http://www.codeproject.com/Articles/7984/Automating-a-specific-instance-of-Visual-Studio-NE
http://msdn.microsoft.com/en-us/library/envdte.outputwindowpane.textdocument.aspx
Automating Visual Studio instance from separate process
Here is what I did.
1. An auxiliary .NET exe
Here is the source code:
using System;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.ComTypes;
using EnvDTE;
namespace VSInstanceFinder
{
public static class Program
{
[DllImport("ole32.dll")]
public static extern int GetRunningObjectTable(int reserved, out IRunningObjectTable prot);
[DllImport("ole32.dll")]
public static extern int CreateBindCtx(int reserved, out IBindCtx ppbc);
public static DTE Find(string solutionFilePath)
{
var numFetched = new IntPtr();
IRunningObjectTable runningObjectTable;
IEnumMoniker monikerEnumerator;
var monikers = new IMoniker[1];
GetRunningObjectTable(0, out runningObjectTable);
runningObjectTable.EnumRunning(out monikerEnumerator);
monikerEnumerator.Reset();
while (monikerEnumerator.Next(1, monikers, numFetched) == 0)
{
IBindCtx ctx;
CreateBindCtx(0, out ctx);
object runningObjectVal;
runningObjectTable.GetObject(monikers[0], out runningObjectVal);
var dte = runningObjectVal as DTE;
try
{
if (dte != null && dte.Solution != null && string.Equals(dte.Solution.FullName, solutionFilePath, StringComparison.OrdinalIgnoreCase))
{
return dte;
}
}
catch
{
}
}
return null;
}
public static OutputWindowPane GetBuildOutputPane(object o)
{
try
{
var dte = (DTE)o;
var outputWindow = (OutputWindow)dte.Windows.Item("{34E76E81-EE4A-11D0-AE2E-00A0C90FFFC3}").Object;
for (var i = 1; i <= outputWindow.OutputWindowPanes.Count; i++)
{
if (outputWindow.OutputWindowPanes.Item(i).Name.Equals("Build", StringComparison.CurrentCultureIgnoreCase))
{
return outputWindow.OutputWindowPanes.Item(i);
}
}
return outputWindow.OutputWindowPanes.Add("Build");
}
catch
{
return null;
}
}
public static string GetBuildLog(object o)
{
try
{
var buildOutputPane = o as OutputWindowPane;
if (buildOutputPane == null || buildOutputPane.TextDocument == null)
{
return "";
}
var sel = buildOutputPane.TextDocument.Selection;
if (sel == null)
{
return "";
}
sel.StartOfDocument();
sel.EndOfDocument(true);
return sel.Text;
}
catch
{
return "";
}
}
public static void Main(string[] args)
{
if (args.Length > 0)
{
var dte = Find(args[0]);
if (dte != null)
{
Console.WriteLine(GetBuildLog(GetBuildOutputPane(dte)));
}
}
}
}
}
2. Powershell
[System.Reflection.Assembly]::LoadFile('C:\utils\VSInstanceFinder.exe')
function buildOneIDE([int]$i, [string]$ts, [string]$solution)
{
$solutionFilePath = "$(Get-Location)\$solution.sln"
$dte = [VSInstanceFinder.Program]::Find($solutionFilePath)
if (!$dte)
{
Write-Host "$solutionFilePath does not seem to be open in any of the running Visual Studio instances"
exit 1
}
$buildOutputPane = [VSInstanceFinder.Program]::GetBuildOutputPane($dte)
$sw = New-Object System.Diagnostics.Stopwatch
$logFileName = "c:\tmp\logs\ui.$i.$solution.$ts.log"
$sw.Start()
$dte.Solution.SolutionBuild.Build($true)
$sw.Stop()
[VSInstanceFinder.Program]::GetBuildLog($buildOutputPane) > $logFileName
"Elapsed Total: $([int]$sw.Elapsed.TotalSeconds) seconds" >> $logFileName
$logFile = dir $logFileName
"$($logFile.Length)`t$($logFile.FullName)"
}
buildOneIDE 1 $(get-date -Format "yyyyMMddHHmmss") "DataSvc"
Does what I need.

Looking to write Bluetooth 'hcitool' equivelant in Windows

I have used Bluez Bluetooth stack in Linux which comes with a handy utility 'hcitool'. Looking to build something like that in Windows with same or equivalent functionality. Specifically, 'hcitool name < MAC >', which shows if the specified device is within range.
Any guidance will be appreciated.
I have Windows SDK v7 with Visual Studio 2010, using C/C++
thanks.
Using my 32feet.NET library something like the following.
EDIT 3rd March: I've now added code to directly lookup the device by address rather than by using device discovery; so that's a simple 'new BluetoothDeviceInfo(...)'.
See if that finds the device you want. This requires the remote device to only be in "Connectable" mode whereas the former requires it to be in "Discoverable" mode. (BTW I've left the discovery code in place.)
EDIT 8th March: Now does a connect (using the SDP API) to check that the device is in range (and in connectable mode).
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using InTheHand.Net.Bluetooth;
using InTheHand.Net;
using InTheHand.Net.Sockets;
using System.Diagnostics;
using System.Net.Sockets;
namespace hcitool
{
partial class Program
{
static bool infoRatherThanName;
static BluetoothAddress _searchAddress;
static int Main(string[] args)
{
if (args.Length < 1) {
Console.WriteLine("Please specify command.");
return 2;
}
var cmd = args[0];
switch (cmd) {
case "name":
infoRatherThanName = false;
break;
case "info":
infoRatherThanName = true;
break;
//-
case "dev":
return ShowRadios();
//case "auth":
// return CauseAuth(GETADDRESS());
default:
throw new NotImplementedException("Command: '" + cmd + "'");
}
if (args.Length < 2) {
Console.WriteLine("Please specify device address.");
return 2;
}
var addrS = args[1];
_searchAddress = BluetoothAddress.Parse(addrS);
//
var dev = new BluetoothDeviceInfo(_searchAddress);
bool isInRange = GetCanConnectTo(dev);
if (isInRange) {
PrintDevice(dev);
} else {
Console.WriteLine("Can't see that device.");
}
//
Console.WriteLine("simple");
return Simple();
//return Fancier();
}
//----
private static int ShowRadios()
{
BluetoothRadio[] list;
try {
list = BluetoothRadio.AllRadios;
} catch (Exception) {
return 1;
}
Debug.Assert(list.Length != 0, "Expect zero radios case to raise an error.");
foreach (var curR in list) {
Console.WriteLine("* {0} '{1}'", curR.LocalAddress, curR.Name);
Console.WriteLine("{0}", curR.SoftwareManufacturer);
Console.WriteLine("{0}", curR.Manufacturer);
Console.WriteLine("{0}", curR.Mode);
}//for
return 0;
}
private static int CauseAuth(BluetoothAddress addr)
{
BluetoothSecurity.PairRequest(addr, null);
return 0;
}
//----
static int Simple()
{
BluetoothDeviceInfo[] devices;
BluetoothDeviceInfo foundDev = null;
var cli = new BluetoothClient();
// Fast: Remembered/Authenticated
devices = cli.DiscoverDevices(255, true, true, false, false);
SimpleCheckDevice(devices, ref foundDev);
if (foundDev == null) {
// Slow: Inquiry
cli.DiscoverDevices(255, false, false, true, false);
SimpleCheckDevice(devices, ref foundDev);
}
//
if (foundDev != null) {
return 0;
} else {
return 1;
}
}
private static void SimpleCheckDevice(IEnumerable<BluetoothDeviceInfo> devices,
ref BluetoothDeviceInfo foundDev)
{
foreach (var cur in devices) {
if (cur.DeviceAddress == _searchAddress) {
foundDev = cur;
PrintDevice(cur);
}
}//for
}
private static void PrintDevice(BluetoothDeviceInfo cur)
{
Console.WriteLine("* Found device: '{0}' ", cur.DeviceName);
if (infoRatherThanName) {
try {
var vs = cur.GetVersions();
Console.WriteLine(vs.Manufacturer);
Console.WriteLine(vs.LmpVersion);
Console.WriteLine(vs.LmpSubversion);
Console.WriteLine(vs.LmpSupportedFeatures);
} catch (Exception ex) {
Console.WriteLine("Failed to get remote device versions info: "
+ ex.Message);
}
}
}
//----
private static bool GetCanConnectTo(BluetoothDeviceInfo device)
{
bool inRange;
Guid fakeUuid = new Guid("{F13F471D-47CB-41d6-9609-BAD0690BF891}");
try {
ServiceRecord[] records = device.GetServiceRecords(fakeUuid);
Debug.Assert(records.Length == 0, "Why are we getting any records?? len: " + records.Length);
inRange = true;
} catch (SocketException) {
inRange = false;
}
return inRange;
}
}
}

Resources