|
I suggest you edit your original post to include all the details you have now revealed with your replies, here, to the other posts.
If your WinForm app depends on getting a list of file-paths from an external app that launches it, then, why not pass the paths as parameters when the external app starts the WinForm app?
Check out the 'SetForegroundWindow and 'SetActiveWindow API's for restoring focus to the external app after you launch the WinForm app: [^].
«While I complain of being able to see only a shadow of the past, I may be insensitive to reality as it is now, since I'm not at a stage of development where I'm capable of seeing it. A few hundred years later another traveler despairing as myself, may mourn the disappearance of what I may have seen, but failed to see.» Claude Levi-Strauss (Tristes Tropiques, 1955)
|
|
|
|
|
"If your WinForm app depends on getting a list of file-paths from an external app that launches it, then, why not pass the paths as parameters when the external app starts the WinForm app?"
This is what I actually did. The problem is that I need to pass 2 rounds of parameters: 1. the app is started, it gets some parameters and it waits; 2. the app is started again, it gets other parameters, do its job and it quits. Because it doesn't quit after the first stage, I had to use SingleInstanceController to avoid multiple instances. That messed up the ShowWithoutActivation.
|
|
|
|
|
Quote: The problem is that I need to pass 2 rounds of parameters
OK, so how was this determination made? What is the process or problem that dictated it?
I seriously doubt this is good solution to the problem.
|
|
|
|
|
That is suitable to my app's workflow. I tested it and it's well intergated with XnView, except that focus issue.
The app's workflow is like this:
- the user wants to arrange some pictures in XnView using the Browser view (rows of thumbnails);
- the user selects the pictures he wants to be arranged (source) and the starts this app;
- the app starts minimized in background, so the user knows that the app got the selected pictures as parameters; he could read the list too in case he forgets which pictures he selected;
- the user selects the target picture (destination) and starts this app again;
- the app gets the target picture as a paramater and does the renaming automatically; after that, the app is closed automatically.
- repeat the process until the pictures are in the expected order.
It feels like a lot of work but it's very fast: just 2 selections and 2 key combos to start the app. Here's a video with this app in action (notice how the files are automatically renamed after the user is doing the selections and starting the app): FileArranger - Streamable[^]
I never seen an app like this before, so I just made one. Instead doing manual renaming to arrange the files, I just let the app to do the heavylifiting.
|
|
|
|
|
Yeah...
Here's the problem with what you're doing. What if the user selects enough images to overwhelm the length of the command line? The limit is 8191 characters.
How does the list of filepaths get assembled into a command line in this XnView software? Is this a plugin to the software or what?
How does your app code make the determination that it's receiving the paths to the first set of images or the rename pattern?
How does the user add more images to the list after the first set of images?
Your "process", as you've described it, doesn't appear to be well thought out.
|
|
|
|
|
"Here's the problem with what you're doing. What if the user selects enough images to overwhelm the length of the command line? The limit is 8191 characters."
There's a hidden setting OpenWithMax that should be added to the [Start] section of xnview.ini. But there's another version of XnView called XnView MP that doesn't have these limitations.
|
|
|
|
|
The limitation is no in XnView, but with the maximum length of the command line you're using to start your external app, 8191 characters.
No, I'm not testing your app.
|
|
|
|
|
I have a problem writing lazy init in a (humanly lazy) fashion.
1st, I am not wondering about and using Lazy<T> for that discussion. This is not the topic at hand...
The topic here is which of the following 2 hand crafted lazy initialisation is the most... "satisfying" (a completely subjective topic, I should warn you)
method 1
public object Property
{
get
{
if (field == null)
field = Create();
return field;
}
}
object field;
object Create() { return new object(); }
method 2
public object Property
{
get
{
field = field ?? Create();
return field;
}
}
object field;
object Create() { return new object(); }
the difference is that in method1 I use an if statement, which is more cumbersome to write, but in method2 I use the (C# 6) null coalesce operator, this is more succinct, but it looks like I might do pointless assignment.
[EDIT] a coworker came up with my favourite answer
public object Property
{
get
{
return field ?? (field = Create());
}
}
object field;
object Create() { return new object(); }
modified 19-Oct-17 20:44pm.
|
|
|
|
|
|
None. Your methods are not thread-safe.
Oh sanctissimi Wilhelmus, Theodorus, et Fredericus!
|
|
|
|
|
I wondered for at least 2 minutes whether I should bother reply to that stupid comment.
I decided to.
Yes, thread safety in that minimalist sample would distract the viewer from my problem. So the lack of it is a feature, not a bug.
modified 20-Oct-17 3:59am.
|
|
|
|
|
Super Lloyd wrote: it is a feature, not a bug.
Ah! It's in the manual!
Bad command or file name. Bad, bad command! Sit! Stay! Staaaay...
AntiTwitter: @DalekDave is now a follower!
|
|
|
|
|
Super Lloyd wrote: that stupid comment. Bernard has never made a stupid comment since he was ten years old; we're fortunate he takes the time to share his deep technical knowledge !
«While I complain of being able to see only a shadow of the past, I may be insensitive to reality as it is now, since I'm not at a stage of development where I'm capable of seeing it. A few hundred years later another traveler despairing as myself, may mourn the disappearance of what I may have seen, but failed to see.» Claude Levi-Strauss (Tristes Tropiques, 1955)
|
|
|
|
|
Thanks.
Oh sanctissimi Wilhelmus, Theodorus, et Fredericus!
|
|
|
|
|
Which is not always a requirement; you don't want to introduce more complexity if this code is only ever called by the UI-thread. And no, you don't add it because of "possible future use" - that's the most lame excuse ever to bloat the code.
Bastard Programmer from Hell
If you can't read my code, try converting it here[^]
|
|
|
|
|
#3 is what ReSharper suggests if you type #1.
"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer
|
|
|
|
|
Does resharper also explain how the first is C# 2.0 compliant, and that option 3 would require at least .NET 3.0? The first example will run on a Windows 2000 machine (if all updates are installed). The second third* won't, ever.
*) third; having trouble with counting and very large numbers
Bastard Programmer from Hell
If you can't read my code, try converting it here[^]
|
|
|
|
|
Eddy Vluggen wrote: The second third* won't, ever.
Yes it will. It's syntactical sugar; so long as the compiler supports it, the compiled code would run on .NET 1.0 if you wanted to.
IL for #1:
IL_0000: ldarg.0
IL_0001: ldfld Foo.field
IL_0006: brtrue.s IL_0014
IL_0008: ldarg.0
IL_0009: ldarg.0
IL_000A: call Foo.Create
IL_000F: stfld Foo.field
IL_0014: ldarg.0
IL_0015: ldfld Foo.field
IL_001A: ret IL for #3:
IL_0000: ldarg.0
IL_0001: ldfld Foo.field
IL_0006: dup
IL_0007: brtrue.s IL_0019
IL_0009: pop
IL_000A: ldarg.0
IL_000B: ldarg.0
IL_000C: call Foo.Create
IL_0011: dup
IL_0012: stloc.0
IL_0013: stfld Foo.field
IL_0018: ldloc.0
IL_0019: ret
The only difference between the two is that #3 uses dup to avoid calling ldfld twice. It's effectively equivalent to:
object temp = field;
if (temp == null)
{
temp = Create();
field = temp;
}
return temp;
(But yes, R# has an option to change the C# language level used by its suggestions, so you could prevent this suggestion if you really wanted to.)
"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer
modified 20-Oct-17 8:26am.
|
|
|
|
|
Richard Deeming wrote: Yes it will. It's syntactical sugar; so long as the compiler supports it, the compiled code would run on .NET 1.0 if you wanted to So you need a newer compiler, and then you can use the older runtime.
Bastard Programmer from Hell
If you can't read my code, try converting it here[^]
|
|
|
|
|
Yes. That's how a lot of the changes to C# are implemented - the compiler recognises the newer code, and compiles it into something that will run on an older version of the framework.
String interpolation; pattern matching; the enhanced "switch" statement; the null-conditional operator - they all compile to IL that will work on older framework versions.
Some of the changes require additional libraries to work - eg: ValueTuple on < 4.7 and async on 4.0 both need extra NuGet packages, and in some cases, changes to class names.
And some changes require additional changes to the CLR or the BCL. But those tend to be quite rare, because the language team are reluctant to make those kinds of changes.
"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer
|
|
|
|
|
Richard Deeming wrote: String interpolation; pattern matching; the enhanced "switch" statement; the null-conditional operator - they all compile to IL that will work on older framework versions. That's what "syntactical sugar" implies; still, without installing the newer compiler (which is usually done by updating the runtime) you're not going to compile that code.
Won't mean much to you; you simply compile and distribute your assembly, as traditional on Windows. Those machines will mostly be running v4 of the runtime or better. I'm currently on a Ubuntu-machine, distributing source
Richard Deeming wrote: And some changes require additional changes to the CLR or the BCL. But those tend to be quite rare, because the language team are reluctant to make those kinds of changes. Microsoft has always been a fan of backward compatibility. TheOldNewThing blog has a nice section on how much effort was put into keeping popular games applications working in Windows 95.
*) ..and I check the dictionary, which clearly states "English". Ah, the US-version..
Bastard Programmer from Hell
If you can't read my code, try converting it here[^]
|
|
|
|
|
The new compiler is on the developer machine
The older runtime is on the client computer.
The client does NOT need the new compiler.
Problem... solved? I believe....
modified 21-Oct-17 2:53am.
|
|
|
|
|
Haha!
Problem is I dislike Resharper, so I would have never know!
|
|
|
|
|
All three methods require a comparison for every access of the property.
Since it should always be defined then the set semantics and ctors should define that rather than the get.
|
|
|
|
|
jschell wrote: All three methods require a comparison for every access of the property. The basic idea of a singleton; do we have an object? If not, make one. Return it.
The OP doesn't specifically request a singleton, otherwise I could point to the "static" modifier, but still for practical purposes seems to be used in that way.
jschell wrote: Since it should always be defined then the set semantics and ctors should define that rather than the get. Nah, a property that defines a getter is going to return a value, and in the exceptional case of an error it will raise an exception. Which parts of those semantics are unclear?
A get (property) can be part of an Interface. It demands you keep your promises
Bastard Programmer from Hell
If you can't read my code, try converting it here[^]
|
|
|
|