How do I write to the output window in Visual Studio 2010 AddIn? - visual-studio-2010

I'm writing a simple Visual Studio 2010 Add-In to do a common copying job here at work (getting dlls from libs sln).
I want the progress of the copying to be written to the output window.
I tried Trace.WriteLine(...) expecting that to make it, but it doesn't when I run the add-in in the debugger. I have not tried it any other way yet.
I found some examples of doing that in Visual Studio 2008, but the required libs are not available to reference.
Can anyone point me to how to write to the output window? My googling skills have failed me.

I've done this for a macro I wrote:
Window window = dte.Windows.Item(EnvDTE.Constants.vsWindowKindOutput);
OutputWindow outputWindow = (OutputWindow) window.Object;
outputWindow.ActivePane.Activate();
outputWindow.ActivePane.OutputString(message);
Here is a link for the DTE Interface:
http://msdn.microsoft.com/en-us/library/envdte.dte(v=VS.100).aspx

As Robert pointed out, John's code will throw an exception when there is no ActivePane. If there is an active pane, it will use whichever pane is active.
One issue I have with Robert's example is depending on where you create the pane, which in my case is the Exec method, it will create multiple panes with the same name each time it is run.
Including my example as to how I got around that issue. Pretty simple, just check for the existence of the window first...
Window window = _applicationObject.Windows.Item( EnvDTE.Constants.vsWindowKindOutput );
OutputWindow outputWindow = ( OutputWindow )window.Object;
OutputWindowPane outputWindowPane = null;
for ( uint i = 1; i <= outputWindow.OutputWindowPanes.Count; i++ )
{
if ( outputWindow.OutputWindowPanes.Item( i ).Name.Equals( OUTPUT_WINDOW_NAME , StringComparison.CurrentCultureIgnoreCase ) )
{
outputWindowPane = outputWindow.OutputWindowPanes.Item( i );
break;
}
}
if ( outputWindowPane == null )
outputWindowPane = outputWindow.OutputWindowPanes.Add( OUTPUT_WINDOW_NAME );
outputWindowPane.OutputString( "Message" );

I am writing a Visual studio add-in and had the same problem, however when trying the above answer I found that the line:
outputWindow.ActivePane.Activate();
gave an error.
NullReferenceException -- Object reference not set to an instance of an object.
However I have now found a slightly different way to solve the problem:
Window window = applicationObject.Windows.Item(Constants.vsWindowKindOutput);
OutputWindow outputWindow = (OutputWindow)window.Object;
OutputWindowPane owp;
owp = outputWindow.OutputWindowPanes.Add("new pane");
owp.OutputString("hello");

Related

Windows Forms c++ cannot set default values in datagrid cells

I've just started working with Windows Forms on Visual Studio 2019. I am most familiar with C++ and thus have been creating an application with C++/CLI. The basis of the project is that I have a schedule generating set of functions these are called in MyForm.h which is the main form originally launched. MyForm.h also opens MyForm2.h when a button is pressed. This MyForm2.h is where I have a problem. I want to allow the user to edit a series of specific settings for the schedule generator. The most user friendly way I've found to do this is with a datagrid using textboxes and checkmarks, but I need to have the original timeslots for the schedule in the datagrid for the user to edit when the open MyForm2.h.
I've looked all over to find how to set default values for a datagrid, but have only come up with two ok methods, both of which have some fatal flaws.
The first was from this microsoft guide.
The problem here is that the solution is written in c#, and I don't know how to implement it in a c++ program.
The second was from a few sites which generally displayed one of two formats which are displayed here in a way that is formatted to how I used them in my forms:
void InitializeComponent()
{
this->dgvStudents = (gcnew System::Windows::Forms::DataGridView());
this->dataGridViewTextBoxColumn1 = (gcnew System::Windows::Forms::DataGridViewTextBoxColumn());
(cli::safe_cast<System::ComponentModel::ISupportInitialize^>(this->dgvStudents))->BeginInit();
this->SuspendLayout();
this->dgvStudents->Columns->Add(this->dataGridViewTextBoxColumn1);
this->dgvStudents->Location = System::Drawing::Point(0, 0);
this->dgvStudents->Name = L"dgvStudents";
this->dgvStudents->Size = System::Drawing::Size(350, 100);
this->dgvStudents->TabIndex = 0;
//
// dataGridViewTextBoxColumn1
//
this->dataGridViewTextBoxColumn1->HeaderText = L"First Name";
this->dataGridViewTextBoxColumn1->Name = L"dataGridViewTextBoxColumn1";
this->AutoScaleDimensions = System::Drawing::SizeF(6, 13);
this->AutoScaleMode = System::Windows::Forms::AutoScaleMode::Font;
this->ClientSize = System::Drawing::Size(638, 261);
this->Controls->Add(this->dgvStudents);
this->Name = L"MyForm3";
this->StartPosition = System::Windows::Forms::FormStartPosition::CenterScreen;
this->Text = L"Exercise";
(cli::safe_cast<System::ComponentModel::ISupportInitialize^>(this->dgvStudents))->EndInit();
this->ResumeLayout(false);
// Option 1
this->dgvStudents->Rows[0]->Cells[0]->Value = "MLP";
// Option 2
this->dgvStudents->Rows->Add("MLP");
}
I have tried putting both options in several various parts of the InitializeComponent() function and it makes no difference. The problem with Option 2 of this second solution is that it will be removed from the code if I change anything in the [Design] part of the MyForm2.h code editor in VS and save it. Weirdly, Option 1 will not be displayed in the [Design] part of the code and instead I will get the error Member Cells not found in class System.Windows.Forms.DataGridViewRowCollection, but if I launch the debugger for the program, both options will be displayed exactly how I want them to be in the GUIs that appear. As previously meantioned though, both options will most likely be removed if I change anything else in the form designer. Any help would be greatly appreciated:)

print pdf silently in c#

I am trying to print pdf silently using adobe reader.
I have taken the example from the following location:
http://www.codeproject.com/Tips/598424/How-to-Silently-Print-PDFs-using-Adobe-Reader-and
I am able to work as desired with the above example code in my localhost.
But when I deploy my application on the server,I am unable to print the PDFs.
In my localhost on button click event,I am creating the PDFs and saving it to one location and printing the same.While printing adobe window opens and prints the PDFs and exits automatically.
The same doesn't work in my server.I am able to create and save PDFs,but adobe is not opening and printing my file.I am not even getting any exception/error.It simply doesn't show up adobe window.
Did anyone face the same issue.
Any help in this regard.
Thanks in advance.
EDIT:
If you are running on a Web Server using ASP.NET or in general IIS the new process executes on the Web server with restricted permissions. I point you out this answer that could explain the cause of your problem.
However the code you are using doesn't print any error message. You probably don't have access to the directory where the AcroRd32.exe is located.
Let's take this function from the article you posted:
public static Boolean PrintPDFs(string pdfFileName)
{
try
{
Process proc = new Process();
proc.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
proc.StartInfo.Verb = "print";
//Define location of adobe reader/command line
//switches to launch adobe in "print" mode
proc.StartInfo.FileName =
#"C:\Program Files (x86)\Adobe\Reader 11.0\Reader\AcroRd32.exe";
proc.StartInfo.Arguments = String.Format(#"/p /h {0}", pdfFileName);
proc.StartInfo.UseShellExecute = false;
proc.StartInfo.CreateNoWindow = true;
proc.Start();
proc.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
if (proc.HasExited == false)
{
proc.WaitForExit(10000);
}
proc.EnableRaisingEvents = true;
proc.Close();
KillAdobe("AcroRd32");
return true;
}
catch
{
return false;
}
}
PrintPDFs uses a process, which is called by the .NET framework using the Process class. In the StartInfo option you look carefully two options are set:
proc.StartInfo.UseShellExecute = false;
proc.StartInfo.CreateNoWindow = true;
proc.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
The first redirect the standard output stream to your application while the second hides the cmd window. The former is handy to use process without showing to the user a command window but the latter hide the console window. The main drawback is, if you're debugging, that you probably won't see error coming through.
One way to debug it would require to add the following to lines:
proc.StartInfo.RedirectStandardOutput = true;
proc.Start();
Console.WriteLine(proc.StandardOutput.ReadToEnd());
Another property you can look at is ExitCode. If that is greather than zero means that your process exit with some error.
hope it helps.
A silent printing can be achieved with an Acroread command line parameters or with a PDF JavaScript event handler (of course, if your PDF producer tool has a possibility to define/inject PDF's OpenAction handler).
See http://pd4ml.com/cookbook/pdf_automated_printing.htm
With the JavaScript approach you are not bound to a printer driver, network name or IP address. On the other hand, JavaScript in Acroread can be disabled, for example, by a corporate security policy.
use this with Ghostscript that is GNU:
ProcessStartInfo info = new ProcessStartInfo();
var FileName = #"C:\ResultadoFormulario_CClastMovements.pdf";
var pathPrinter = #"\\Server\namePrinter";
info.CreateNoWindow = true;
var pathGsw = #"path gswin64c here\";
info.WindowStyle = ProcessWindowStyle.Hidden;
string strCmdText = $"{pathGsw}gswin64c.exe -sDEVICE=mswinpr2 -dBATCH -dNOPAUSE -dNOPROMPT -dNoCancel -dPDFFitPage -sOutputFile=\"%printer%{direccionImpresora}\" \"{FileName}\"";
Process.Start("CMD.exe", strCmdText);

DataGridView problem when adding columns

Hey guys! First time I use Visual Studio 2008 Windows Form Application with C++.
I want to put a dataGridView on my form. That is ok. But when adding one column, on the gridView appear 2 columns. First with no header (which I dont want) and the second is ok(my column). I tried to set the column number from code, but the same thing happens.
Any idea to solve this?
Thanks,
Andrew
//
// table
//
this->table->AllowUserToAddRows = false;
this->table->AllowUserToDeleteRows = false;
this->table->ColumnHeadersHeightSizeMode = System::Windows::Forms::DataGridViewColumnHeadersHeightSizeMode::AutoSize;
this->table->Columns->AddRange(gcnew cli::array< System::Windows::Forms::DataGridViewColumn^ >(1) {this->Column1});
this->table->Location = System::Drawing::Point(13, 89);
this->table->Name = L"table";
this->table->ReadOnly = true;
this->table->Size = System::Drawing::Size(240, 150);
this->table->TabIndex = 2;
//
// Column1
//
this->Column1->HeaderText = L"Column1";
this->Column1->Name = L"Column1";
this->Column1->ReadOnly = true;
Are you adding the column in the constructor?
I've had a problem in the past where items added in the constructor get added twice, because (I think) the constructor gets called to make the control appear in the designer view, (which then gets added to the instance) and then again when you run your program.
If that is what's happening for you, you need to check that you aren't in design mode.
There are a few different ways to check this, depending on context - see How to tell if .NET code is being run by Visual Studio designer

Is there an event triggered when dte.Solution.SolutionBuild.StartupProjects changes?

I am building a visual studio 2010 Add-in for internal use in my company. I would like to customize the main window caption to display the name of the current start up project. I can set the caption of the main window with the following code:
DTE d = GlobalClass.dte2 as DTE;
IntPtr hWnd = new System.IntPtr(d.MainWindow.HWnd);
if (d.Solution.SolutionBuild.StartupProjects != null)
{
object[] sStartUpProject = (object[])d.Solution.SolutionBuild.StartupProjects;
string Caption = d.MainWindow.Caption + "Current Project: " + (string)sStartUpProject[0];
SendMessage(hWnd, WM_SETTEXT, new IntPtr(0), Caption);
}
I can fire this code whenever a window is created or activated, but this does not update the Caption if the user changes the startup project in the solution explorer (or my add-in) and doesn't move to another window in Visual Studio. I would like the caption to update as soon as the change was made.
Yes, you need subscribe to IVsMonitorSelection events and handle SEID_StartupProject in OnElementValueChanged().
Check out this code, it's quite self-explaining:
https://bitbucket.org/thirteen/switchstartupproject/src/a80f0deb737c/SwitchStartupProject/SwitchStartupProjectPackage.cs

How do I add Debug Breakpoints to lines displayed in a "Find Results" window in Visual Studio

In Visual Studio 2005-2015 it is possible to find all lines containing certain references and display them in a "Find Results" window.
Now that these result lines are displayed, is there any keyboard shortcut that would allow adding debug breakpoints to all of them?
This answer does not work for Visual Studio 2015 or later. A more recent answer can be found here.
You can do this fairly easily with a Visual Studio macro. Within Visual Studio, hit Alt-F11 to open the Macro IDE and add a new module by right-clicking on MyMacros and selecting Add|Add Module...
Paste the following in the source editor:
Imports System
Imports System.IO
Imports System.Text.RegularExpressions
Imports EnvDTE
Imports EnvDTE80
Imports EnvDTE90
Imports System.Diagnostics
Public Module CustomMacros
Sub BreakpointFindResults()
Dim findResultsWindow As Window = DTE.Windows.Item(Constants.vsWindowKindFindResults1)
Dim selection As TextSelection
selection = findResultsWindow.Selection
selection.SelectAll()
Dim findResultsReader As New StringReader(selection.Text)
Dim findResult As String = findResultsReader.ReadLine()
Dim findResultRegex As New Regex("(?<Path>.*?)\((?<LineNumber>\d+)\):")
While Not findResult Is Nothing
Dim findResultMatch As Match = findResultRegex.Match(findResult)
If findResultMatch.Success Then
Dim path As String = findResultMatch.Groups.Item("Path").Value
Dim lineNumber As Integer = Integer.Parse(findResultMatch.Groups.Item("LineNumber").Value)
Try
DTE.Debugger.Breakpoints.Add("", path, lineNumber)
Catch ex As Exception
' breakpoints can't be added everywhere
End Try
End If
findResult = findResultsReader.ReadLine()
End While
End Sub
End Module
This example uses the results in the "Find Results 1" window; you might want to create an individual shortcut for each result window.
You can create a keyboard shortcut by going to Tools|Options... and selecting Keyboard under the Environment section in the navigation on the left. Select your macro and assign any shortcut you like.
You can also add your macro to a menu or toolbar by going to Tools|Customize... and selecting the Macros section in the navigation on the left. Once you locate your macro in the list, you can drag it to any menu or toolbar, where it its text or icon can be customized to whatever you want.
If you can search for the word exactly, you can use a pair of keyboard shortcuts to do it quickly.
Tools -> Options -> Enviroment -> Keyboard
Edit.GoToFindResults1NextLocation
EditorContextMenus.CodeWindow.Breakpoint.InsertBreakpoint
Assign them to Control+Alt+F11 and F10 and you can go through all the results very quickly. I haven't found a shortcut for going to the next reference however.
I needed something similar to disable all breakpoints and place a breakpoint on every "Catch ex as Exception". However, I expanded this a little so it will place a breakpoint at every occurance of the string you have selected. All you need to do with this is highlight the string you want to have a breakpoint on and run the macro.
Sub BreakPointAtString()
Try
DTE.ExecuteCommand("Debug.DisableAllBreakpoints")
Catch ex As Exception
End Try
Dim tsSelection As String = DTE.ActiveDocument.Selection.text
DTE.ActiveDocument.Selection.selectall()
Dim AllText As String = DTE.ActiveDocument.Selection.Text
Dim findResultsReader As New StringReader(AllText)
Dim findResult As String = findResultsReader.ReadLine()
Dim lineNum As Integer = 1
Do Until findResultsReader.Peek = -1
lineNum += 1
findResult = findResultsReader.ReadLine()
If Trim(findResult) = Trim(tsSelection) Then
DTE.ActiveDocument.Selection.GotoLine(lineNum)
DTE.ExecuteCommand("Debug.ToggleBreakpoint")
End If
Loop
End Sub
Hope it works for you :)
Paul, thanks a lot, but I have the following error (message box), may be I need to restart my PC:
Error
---------------------------
Error HRESULT E_FAIL has been returned from a call to a COM component.
---------------------------
OK
---------------------------
I would propose the following solution that's very simple but it works for me
Sub BreakPointsFromSearch()
Dim n As Integer = InputBox("Enter the number of search results")
For i = 1 To n
DTE.ExecuteCommand("Edit.GoToNextLocation")
DTE.ExecuteCommand("Debug.ToggleBreakpoint")
Next
End Sub

Resources