Run script when finished saving file - Visual Studio Extensibility - c#

Can someone give me some sample code for Visual Studio Extensibility where I can grab the text from a document, when the Save event ends, and run a script in C # with that text (example, trigger a Web service for certain file extensions). It could also be a new button (for example, save in the web service).

You can subscribe to the DocumentSaved event:
events = DTE.Events;
documentEvents = events.DocumentEvents;
documentEvents.DocumentSaved += OnDocumentSaved;
In the OnDocumentSaved handler with EnvDTE.Document you can get the document path as doc.FullName.
To get text from EnvDTE.Document:
TextDocument td = (TextDocument)(doc.Object("TextDocument"));
var p = td.StartPoint.CreateEditPoint();
string s = p.GetText(td.EndPoint);
See In VisualStudio DTE, how to get the contents of the ActiveDocument? and https://vlasovstudio.com/visual-commander/extensions.html for complete samples.

Related

How to set the download folder for Edge in Selenium?

I am writing automated tests using Selenium. I want to set the download directory in Edge so that I can download files as part of my test. There is an EdgeOptions object that I can provide when creating the EdgeDriver, but I don't know what to set on the EdgeOptions.
I know the equivalent of how to do this in Chrome
chromeOptions.AddUserProfilePreference("download.default_directory", #"C:\temp")
and Firefox
firefoxOptions.SetPreference("browser.download.dir", #"C:\temp")
But, how do I do the same thing in Edge? And get it to download automatically without a save prompt?
As #Prany already mentioned, probably there is no way to set download automatically. And if I right understood, you want to handle with native window dialogue, when you are clicking on download button. Selenium cannot interact with native windows, but you can use this framework. The sample code would be like this:
// Press the A Key Down
KeyboardSimulator.KeyDown(Keys.A);
// Let the A Key back up
KeyboardSimulator.KeyUp(Keys.A);
// Press A down, and let up (same as two above)
KeyboardSimulator.KeyPress(Keys.A);
// Simulate (Ctrl + C) shortcut, which is copy for most applications
KeyboardSimulator.SimulateStandardShortcut(StandardShortcut.Copy);
// This does the same as above
KeyboardSimulator.KeyDown(Keys.Control);
KeyboardSimulator.KeyPress(Keys.C);
KeyboardSimulator.KeyUp(Keys.Control);
So you can simulate Ctrl + V keyboard action and Enter action. Hope it helps.
You can do this for Edge like this:
// hide driver Console? true/false
EdgeDriverService service = EdgeDriverService.CreateDefaultService();
service.HideCommandPromptWindow = true; // hide Console
// change Standard-Download-Path
EdgeOptions options = new EdgeOptions();
var downloadDirectory = "C:\temp";
// Setting custom download directory
options.AddUserProfilePreference("download.default_directory", downloadDirectory);
// start Selenium Driver:
webdriver = new EdgeDriver(service, options);
// max. Window
webdriver.Manage().Window.Maximize();

WPF Printing (XpsDocumentWriter) working in debug but not in deployment

Hopefully some of the experienced WPF developers have come across this issue before.
BACKGROUND: This information is probably not necessary to helping fixing the problem, but in case it is relevant.
My solution consists of three projects. A front-end GUI, a business logic service, and a printer service. The three projects have IPC via named pipes. The business logic hands the printing logic a label type and a pallet id.
The Problem: The printing logic then creates the label and prints it (by adding it to the print queue of a printer) As the title suggests this all works fine when I am debugging in visual studio. However when I deploy / install the services on my developer pc it is not working.
Update: It is not throwing an exception but I am only logging "About to send doc to printer" and not the line "Sent doc to printer" So it is hanging on the dw1.Write(fixedDoc); line
More Information: I am using .Net 4.0 in the printing project / visual studio 2013
public void printLabel(string labelType, string _palletID = null)
{
try
{
ILabelTemplate Label = createLabel(labelType, _palletID);
PrintDialog pd = new PrintDialog();
FixedDocument fixedDoc = new FixedDocument();
PageContent pageContent = new PageContent();
FixedPage fixedPage = getFixedPage();
fixedDoc.DocumentPaginator.PageSize = new System.Windows.Size(fixedPage.Width, fixedPage.Height);
IXamlTemplate vm = CreateViewModel(Label);
ILabelPrintDocument template = CreateTemplate(Label);
template.dockPanel.DataContext = vm;
template.dockPanel.Height = fixedPage.Height;
template.dockPanel.Width = fixedPage.Width;
template.dockPanel.UpdateLayout();
fixedPage.Children.Add(template.dockPanel);
((System.Windows.Markup.IAddChild)pageContent).AddChild(fixedPage);
fixedDoc.Pages.Add(pageContent);
XpsDocumentWriter dw1 = PrintQueue.CreateXpsDocumentWriter(new System.Printing.PrintQueue(new System.Printing.PrintServer(), Label.PrinterName));
Library.WriteErrorLog("About to send doc to printer");
dw1.Write(fixedDoc);
Library.WriteErrorLog("Sent doc to printer");
}
catch (Exception ex)
{
Library.WriteErrorLog(ex);
}
SOLVED ... kind of
After several hours of trying different things and reading about this, I found that it was due to my application running as me when I'm debugging but as a LOCAL SYSTEM when I have it deployed. And a local system service does not have access to network resources such as printers. Despite learning this, I then started down the path of how to make a C# service print. Well after seeing many posts (too late in the game to be very helpful)
Like this and also this one I have learned that I was going down the wrong path.
The moral of the story is, if you're reading this post you're probably not at the level of "writing your own printing DLL using the Win32 API (in C/C++ for instance), then use it from your service with P/Invoke"
The solution that did work for me was instead of running this project as a service which was started via my GUI. I have instead turned it into a process which is still started and stopped via my GUI.
The code in question is
if (File.Exists(AppDomain.CurrentDomain.BaseDirectory + "\\yourAppNameGoesHere.exe"))
{
Process.Start(AppDomain.CurrentDomain.BaseDirectory + "\\yourAppNameGoesHere.exe");
}
then when the GUI is closed I run the code
if (File.Exists(AppDomain.CurrentDomain.BaseDirectory + "\\yourAppNameGoesHere.exe"))
{
Process[] myapps = Process.GetProcesses("yourAppNameGoesHere.exe");
foreach (Process _p in myapps)
{
_p.Kill();
}
}

Running Matlab GUI from C#

In my project, I am integrating Matlab GUI application with in a C# application.
The solution I thought about is to create a standalone application from the Matlab GUI and start it via a button in C#:
Process exeProcess = Process.Start("Data_Capture_Direct_call.exe");
if(!exeProcess.HasExited)
{
exeProcess.WaitForExit();
}
exeProcess.Close();
The problem is that after the splash screen of Matlab GUI is closed and before the actual program opens, C# detects that the program has been closed already and carries on to the next line.
In addition, the next few lines of code are not properly executed:
List<String> Movement = new List<String>();
List<String> Repetition = new List<String>();
List<String> Duration = new List<String>();
using (CsvFileReader reader = new CsvFileReader("capture.csv"))
{
CsvRow row = new CsvRow();
while (reader.ReadRow(row))
{
Movement.Add(row[0]);
Repetition.Add(row[1]);
Duration.Add(row[2]);
}
}
for (int i = 1; i < Movement.Count; i++)
{
dataGridView1.Rows.Add(i, Movement[i], Repetition[i], Duration[i]);
}
What happens is that after the C# wrongly detects closure of the process, the capture.csv file becomes empty and data is not loaded into the data grid.
Please let me know where I am making a mistake or if there is a better way to do this!
In my solution you should do some settings before starting code in order to use Matlab instance in a C# application.
Adding neccessary dll :
First we will add dll reference with COM interface. Click RMB on project and choose [Add Reference] option. In new window click COM tab. In search text box write 'Matlab'. Then choose "Matlab Application (Version 7.10) Type Library".
You should get references like below :
Now you can easily do whatever you can do on Matlab in C# . Lets give an basic example :
var acCtx = Type.GetTypeFromProgID("matlab.application.single");
var matlab = (MLApp.MLApp)Activator.CreateInstance(acCtx);
these two lines are creating of matlab instance in code.Now let's make a easy computation on Matlab.
Console.WriteLine(matlab.Execute("1+2")); // This will output 3 on console.
matlab.Quit(); // you should close matlab in order to clean memory
Lets give solution to your actual problem.You want to execute a Matlab GUI program.And I think your Gui is recording some data to CSV file.Then your C# program processes that data.You should note that you can call your GUI in Matlab just writing your name of program as command.Suppose that you have a GUI called myGui.m.You can call that gui by calling myGui in command line as you can write 1+2 to get 3.
Let's call gui.
matlab.Execute("myGui"); // This will execute your Gui. You can use buttons to save data to CSV file
matlab.Quit();
I have extended example on this page :
Source

Detect Document Reload has occured on server

I have an winform/OCX that consumes a qlikview document. We have gotten a patch from QV so that RefreshDocument works in the OCX as the RefreshDocument does in QV application. But the Application shows a nice enabled button when the document has been reload on the server.
Does anyone know what needs to be done to detect that. Either in C# or in macro code or ManagementAPI ?
This is the ReloadDocument Code.
private void button2_Click(object sender, EventArgs e)
{
var myBloodybookmarkHack = "dynaBookmark" + Guid.NewGuid().ToString().Replace("-","");
axQlikOCX1.ActiveDocument.CreateUserBookmark(myBloodybookmarkHack, true);
//axQlikOCX1.OpenDocument(#"qvp://qvSeverName/path/MyDocument.qvw?bookmark=Server\dynaBookmarkb5aa82ae467540fdb0d18bb499044ed9");
axQlikOCX1.RefreshDocument();
axQlikOCX1.ActiveDocument.RecallUserBookmark(myBloodybookmarkHack);
axQlikOCX1.ActiveDocument.RemoveUserBookmark(myBloodybookmarkHack);
}
By suppressing the paint event I get this to run pretty ok. Next patch will include that it keeps the selections (Will be fixed in 11.2 servicerelease 6).
You need to detect if CreateUserBookmark was successfull or not and not restore the bookmark if the creation failed.
This code works in QV 11.2 serviceRelease 5.
The filesystem reads a new modified time when the qvw file is rewritten after load. Assuming the data portion of this application is not broken out from the QVW file. Likely, you could come very close to accomplishing this by checking for new timestamps. Alternatively, if logging is enabled in the qvw document you could log read the text file* that QlikView generates to accomplish the same thing.
*The text file writes are delayed sometimes so your file might be refreshed a little bit before the log states that it is.
We ended up using the QV Management api to get the last task reload time
Download the Qv management api demo from QV
This code shows you how to get tasks on a document. Through that you get when "last document reload task" was finished.
private DateTime GetLastDocumentRun(string documentName)
{
string QMS = "http://MyQlikviewserver:4799/QMS/Service";
var client = new QMSClient("BasicHttpBinding_IQMS", QMS);
string key = client.GetTimeLimitedServiceKey();
ServiceKeyClientMessageInspector.ServiceKey = key;
var taskStatusFilter = new TaskStatusFilter();
var clientTaskStatuses = client.GetTaskStatuses(taskStatusFilter, TaskStatusScope.All);
foreach (var taskStatus in clientTaskStatuses)
{
Trace.WriteLine(taskStatus.General.TaskName);
if (taskStatus.General.TaskName.ToLower().Contains(documentName.ToLower()))
{
string fin = taskStatus.Extended.FinishedTime + "";
DateTime finishedTime;
if (DateTime.TryParse(fin, out finishedTime))
return finishedTime;
Logger.ErrMessage("QvManagementApi.GetLastDocumentRun",new Exception("Task finished time did not return a valid datetime value:" + fin));
return DateTime.MinValue;
}
}
return DateTime.MinValue;
}
This is slow, so you should run on a different thread.
Also this does not show if the task is successfully reloaded. We haven't fix that yet but on taskStatus.Extended you have the last log, which you can text parse to get if it was successfully reloaded or not.
If I understand correctly you want to know if a document has finished reloading on a QlikView server right?
I've you OCX application has a constant connection, you could evaluate the ReloadTime() function in the document which would tell you when the document was last reloaded. If you listen for the function and issuing a DocumentRefresh while doing this, then you would get a changed timestamp once the newly reloaded document becomes avaible on the server.
The code your posting, does not reload a QlikView document. At least not in QlikView lingo, it just open the documents on the server.
Please elaborate if I misunderstand you.
Regards Torber

microsoft.interop.selection text

Before asking my question I would like to describe briefly background of my problem: I'm developing ms word COM addin on C# and I need to handle user's text selections. Now I'm able to catch selection event - it's look like
Microsoft.Interop.Word._Application app;
app = (Word._Application )Application; // Application object comes on addin's connection
app.Application.WindowSelectionChange+=
new Word.ApplicationEvents4_WindowSelectionChangeEventHandler(selChange);
///
void selChange(Word.Selection selection){
MessageBox.Show(selection.Text); // this is my problem, Text property is not available
}
// property Text doesn't exist,but documentation tells that it exists. I suspect, that this property is not available for ms word 2007 - in the documentation only 2003,2010 versions are mentioned. But how I can do something like selection.getSelectedText()? I tryed to play with selection.Rows, selection.Rows[0],selection.Words,selection.Words[0] - no success.
According to the documentation, the Selection.Text property should be available for Word 2007 as well. I made a small sample implementation of your case to test it, and I cannot make it fail on Word 2010 and 2013 at least:
var wordApplication = new Application() { Visible = true };
wordApplication.Documents.Add();
wordApplication.WindowSelectionChange += delegate(Selection mySelection) { Console.WriteLine(mySelection.Text); };
So, I suggest you check that you have included the right namespaces and that the Selection interface you are using are actually the one from the Microsoft.Office.Interop.Word namespace.

Categories